GNU Linux-libre 4.9.301-gnu1
[releases.git] / arch / mips / kernel / vdso.c
1 /*
2  * Copyright (C) 2015 Imagination Technologies
3  * Author: Alex Smith <alex.smith@imgtec.com>
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation;  either version 2 of the  License, or (at your
8  * option) any later version.
9  */
10
11 #include <linux/binfmts.h>
12 #include <linux/elf.h>
13 #include <linux/err.h>
14 #include <linux/init.h>
15 #include <linux/ioport.h>
16 #include <linux/irqchip/mips-gic.h>
17 #include <linux/kernel.h>
18 #include <linux/mm.h>
19 #include <linux/sched.h>
20 #include <linux/slab.h>
21 #include <linux/timekeeper_internal.h>
22
23 #include <asm/abi.h>
24 #include <asm/page.h>
25 #include <asm/vdso.h>
26
27 /* Kernel-provided data used by the VDSO. */
28 static union mips_vdso_data vdso_data __page_aligned_data;
29
30 /*
31  * Mapping for the VDSO data/GIC pages. The real pages are mapped manually, as
32  * what we map and where within the area they are mapped is determined at
33  * runtime.
34  */
35 static struct page *no_pages[] = { NULL };
36 static struct vm_special_mapping vdso_vvar_mapping = {
37         .name = "[vvar]",
38         .pages = no_pages,
39 };
40
41 static void __init init_vdso_image(struct mips_vdso_image *image)
42 {
43         unsigned long num_pages, i;
44         unsigned long data_pfn;
45
46         BUG_ON(!PAGE_ALIGNED(image->data));
47         BUG_ON(!PAGE_ALIGNED(image->size));
48
49         num_pages = image->size / PAGE_SIZE;
50
51         data_pfn = __phys_to_pfn(__pa_symbol(image->data));
52         for (i = 0; i < num_pages; i++)
53                 image->mapping.pages[i] = pfn_to_page(data_pfn + i);
54 }
55
56 static int __init init_vdso(void)
57 {
58         init_vdso_image(&vdso_image);
59
60 #ifdef CONFIG_MIPS32_O32
61         init_vdso_image(&vdso_image_o32);
62 #endif
63
64 #ifdef CONFIG_MIPS32_N32
65         init_vdso_image(&vdso_image_n32);
66 #endif
67
68         return 0;
69 }
70 subsys_initcall(init_vdso);
71
72 void update_vsyscall(struct timekeeper *tk)
73 {
74         vdso_data_write_begin(&vdso_data);
75
76         vdso_data.xtime_sec = tk->xtime_sec;
77         vdso_data.xtime_nsec = tk->tkr_mono.xtime_nsec;
78         vdso_data.wall_to_mono_sec = tk->wall_to_monotonic.tv_sec;
79         vdso_data.wall_to_mono_nsec = tk->wall_to_monotonic.tv_nsec;
80         vdso_data.cs_shift = tk->tkr_mono.shift;
81
82         vdso_data.clock_mode = tk->tkr_mono.clock->archdata.vdso_clock_mode;
83         if (vdso_data.clock_mode != VDSO_CLOCK_NONE) {
84                 vdso_data.cs_mult = tk->tkr_mono.mult;
85                 vdso_data.cs_cycle_last = tk->tkr_mono.cycle_last;
86                 vdso_data.cs_mask = tk->tkr_mono.mask;
87         }
88
89         vdso_data_write_end(&vdso_data);
90 }
91
92 void update_vsyscall_tz(void)
93 {
94         if (vdso_data.clock_mode != VDSO_CLOCK_NONE) {
95                 vdso_data.tz_minuteswest = sys_tz.tz_minuteswest;
96                 vdso_data.tz_dsttime = sys_tz.tz_dsttime;
97         }
98 }
99
100 int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
101 {
102         struct mips_vdso_image *image = current->thread.abi->vdso;
103         struct mm_struct *mm = current->mm;
104         unsigned long gic_size, vvar_size, size, base, data_addr, vdso_addr;
105         struct vm_area_struct *vma;
106         struct resource gic_res;
107         int ret;
108
109         if (down_write_killable(&mm->mmap_sem))
110                 return -EINTR;
111
112         /* Map delay slot emulation page */
113         base = mmap_region(NULL, STACK_TOP, PAGE_SIZE,
114                            VM_READ | VM_EXEC |
115                            VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
116                            0);
117         if (IS_ERR_VALUE(base)) {
118                 ret = base;
119                 goto out;
120         }
121
122         /*
123          * Determine total area size. This includes the VDSO data itself, the
124          * data page, and the GIC user page if present. Always create a mapping
125          * for the GIC user area if the GIC is present regardless of whether it
126          * is the current clocksource, in case it comes into use later on. We
127          * only map a page even though the total area is 64K, as we only need
128          * the counter registers at the start.
129          */
130         gic_size = gic_present ? PAGE_SIZE : 0;
131         vvar_size = gic_size + PAGE_SIZE;
132         size = vvar_size + image->size;
133
134         /*
135          * Find a region that's large enough for us to perform the
136          * colour-matching alignment below.
137          */
138         if (cpu_has_dc_aliases)
139                 size += shm_align_mask + 1;
140
141         base = get_unmapped_area(NULL, 0, size, 0, 0);
142         if (IS_ERR_VALUE(base)) {
143                 ret = base;
144                 goto out;
145         }
146
147         /*
148          * If we suffer from dcache aliasing, ensure that the VDSO data page
149          * mapping is coloured the same as the kernel's mapping of that memory.
150          * This ensures that when the kernel updates the VDSO data userland
151          * will observe it without requiring cache invalidations.
152          */
153         if (cpu_has_dc_aliases) {
154                 base = __ALIGN_MASK(base, shm_align_mask);
155                 base += ((unsigned long)&vdso_data - gic_size) & shm_align_mask;
156         }
157
158         data_addr = base + gic_size;
159         vdso_addr = data_addr + PAGE_SIZE;
160
161         vma = _install_special_mapping(mm, base, vvar_size,
162                                        VM_READ | VM_MAYREAD,
163                                        &vdso_vvar_mapping);
164         if (IS_ERR(vma)) {
165                 ret = PTR_ERR(vma);
166                 goto out;
167         }
168
169         /* Map GIC user page. */
170         if (gic_size) {
171                 ret = gic_get_usm_range(&gic_res);
172                 if (ret)
173                         goto out;
174
175                 ret = io_remap_pfn_range(vma, base,
176                                          gic_res.start >> PAGE_SHIFT,
177                                          gic_size,
178                                          pgprot_noncached(PAGE_READONLY));
179                 if (ret)
180                         goto out;
181         }
182
183         /* Map data page. */
184         ret = remap_pfn_range(vma, data_addr,
185                               virt_to_phys(&vdso_data) >> PAGE_SHIFT,
186                               PAGE_SIZE, PAGE_READONLY);
187         if (ret)
188                 goto out;
189
190         /* Map VDSO image. */
191         vma = _install_special_mapping(mm, vdso_addr, image->size,
192                                        VM_READ | VM_EXEC |
193                                        VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC,
194                                        &image->mapping);
195         if (IS_ERR(vma)) {
196                 ret = PTR_ERR(vma);
197                 goto out;
198         }
199
200         mm->context.vdso = (void *)vdso_addr;
201         ret = 0;
202
203 out:
204         up_write(&mm->mmap_sem);
205         return ret;
206 }