History

Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc

Pull sparc fix from David Miller: "Build regression fix" * git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc: sparc: Fix VDSO build with older binutils.

Linus Torvalds committed 8 years ago

Commit e5f6d9a2 parents c300af2 caf539c7 files · +335 −62Browse files

Unified · Split

7 files
  1. arch/sparc/include/asm/vdso.h +0 −2
  2. arch/sparc/vdso/vclock_gettime.c +129 −20
  3. arch/sparc/vdso/vdso-layout.lds.S +0 −3
  4. arch/sparc/vdso/vdso.lds.S +2 −0
  5. arch/sparc/vdso/vdso2c.h +1 −16
  6. arch/sparc/vdso/vdso32/vdso32.lds.S +2 −0
  7. arch/sparc/vdso/vma.c +201 −21
arch/sparc/include/asm/vdso.h+0−2
@@ -9,8 +9,6 @@ struct vdso_image { · 8 unmodified lines
99 void *data;
1010 unsigned long size; /* Always a multiple of PAGE_SIZE */
1111
12− unsigned long tick_patch, tick_patch_len;
13−
1412 long sym_vvar_start; /* Negative offset to the vvar area */
1513 };
1614
arch/sparc/vdso/vclock_gettime.c+129−20
@@ -90,16 +90,15 @@ notrace static __always_inline u64 vread_tick(void) · 89 unmodified lines
9090 {
9191 u64 ret;
9292
93− __asm__ __volatile__("1:\n\t"
94− "rd %%tick, %0\n\t"
95− ".pushsection .tick_patch, \"a\"\n\t"
96− ".word 1b - ., 1f - .\n\t"
97− ".popsection\n\t"
98− ".pushsection .tick_patch_replacement, \"ax\"\n\t"
99− "1:\n\t"
100− "rd %%asr24, %0\n\t"
101− ".popsection\n"
102− : "=r" (ret));
93+ __asm__ __volatile__("rd %%tick, %0" : "=r" (ret));
94+ return ret;
95+}
96+
97+notrace static __always_inline u64 vread_tick_stick(void)
98+{
99+ u64 ret;
100+
101+ __asm__ __volatile__("rd %%asr24, %0" : "=r" (ret));
103102 return ret;
104103 }
105104 #else
@@ -107,16 +106,18 @@ notrace static __always_inline u64 vread_tick(void) · 1 unmodified line
107106 {
108107 register unsigned long long ret asm("o4");
109108
110− __asm__ __volatile__("1:\n\t"
111− "rd %%tick, %L0\n\t"
112− "srlx %L0, 32, %H0\n\t"
113− ".pushsection .tick_patch, \"a\"\n\t"
114− ".word 1b - ., 1f - .\n\t"
115− ".popsection\n\t"
116− ".pushsection .tick_patch_replacement, \"ax\"\n\t"
117− "1:\n\t"
118− "rd %%asr24, %L0\n\t"
119− ".popsection\n"
109+ __asm__ __volatile__("rd %%tick, %L0\n\t"
110+ "srlx %L0, 32, %H0"
111+ : "=r" (ret));
112+ return ret;
113+}
114+
115+notrace static __always_inline u64 vread_tick_stick(void)
116+{
117+ register unsigned long long ret asm("o4");
118+
119+ __asm__ __volatile__("rd %%asr24, %L0\n\t"
120+ "srlx %L0, 32, %H0"
120121 : "=r" (ret));
121122 return ret;
122123 }
@@ -132,6 +133,16 @@ notrace static __always_inline u64 vgetsns(struct vvar_data *vvar) · 9 unmodified lines
132133 return v * vvar->clock.mult;
133134 }
134135
136+notrace static __always_inline u64 vgetsns_stick(struct vvar_data *vvar)
137+{
138+ u64 v;
139+ u64 cycles;
140+
141+ cycles = vread_tick_stick();
142+ v = (cycles - vvar->clock.cycle_last) & vvar->clock.mask;
143+ return v * vvar->clock.mult;
144+}
145+
135146 notrace static __always_inline int do_realtime(struct vvar_data *vvar,
136147 struct timespec *ts)
137148 {
@@ -152,6 +163,26 @@ notrace static __always_inline int do_realtime(struct vvar_data *vvar, · 14 unmodified lines
152163 return 0;
153164 }
154165
166+notrace static __always_inline int do_realtime_stick(struct vvar_data *vvar,
167+ struct timespec *ts)
168+{
169+ unsigned long seq;
170+ u64 ns;
171+
172+ do {
173+ seq = vvar_read_begin(vvar);
174+ ts->tv_sec = vvar->wall_time_sec;
175+ ns = vvar->wall_time_snsec;
176+ ns += vgetsns_stick(vvar);
177+ ns >>= vvar->clock.shift;
178+ } while (unlikely(vvar_read_retry(vvar, seq)));
179+
180+ ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
181+ ts->tv_nsec = ns;
182+
183+ return 0;
184+}
185+
155186 notrace static __always_inline int do_monotonic(struct vvar_data *vvar,
156187 struct timespec *ts)
157188 {
@@ -172,6 +203,26 @@ notrace static __always_inline int do_monotonic(struct vvar_data *vvar, · 14 unmodified lines
172203 return 0;
173204 }
174205
206+notrace static __always_inline int do_monotonic_stick(struct vvar_data *vvar,
207+ struct timespec *ts)
208+{
209+ unsigned long seq;
210+ u64 ns;
211+
212+ do {
213+ seq = vvar_read_begin(vvar);
214+ ts->tv_sec = vvar->monotonic_time_sec;
215+ ns = vvar->monotonic_time_snsec;
216+ ns += vgetsns_stick(vvar);
217+ ns >>= vvar->clock.shift;
218+ } while (unlikely(vvar_read_retry(vvar, seq)));
219+
220+ ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
221+ ts->tv_nsec = ns;
222+
223+ return 0;
224+}
225+
175226 notrace static int do_realtime_coarse(struct vvar_data *vvar,
176227 struct timespec *ts)
177228 {
@@ -227,6 +278,31 @@ int · 49 unmodified lines
227278 clock_gettime(clockid_t, struct timespec *)
228279 __attribute__((weak, alias("__vdso_clock_gettime")));
229280
281+notrace int
282+__vdso_clock_gettime_stick(clockid_t clock, struct timespec *ts)
283+{
284+ struct vvar_data *vvd = get_vvar_data();
285+
286+ switch (clock) {
287+ case CLOCK_REALTIME:
288+ if (unlikely(vvd->vclock_mode == VCLOCK_NONE))
289+ break;
290+ return do_realtime_stick(vvd, ts);
291+ case CLOCK_MONOTONIC:
292+ if (unlikely(vvd->vclock_mode == VCLOCK_NONE))
293+ break;
294+ return do_monotonic_stick(vvd, ts);
295+ case CLOCK_REALTIME_COARSE:
296+ return do_realtime_coarse(vvd, ts);
297+ case CLOCK_MONOTONIC_COARSE:
298+ return do_monotonic_coarse(vvd, ts);
299+ }
300+ /*
301+ * Unknown clock ID ? Fall back to the syscall.
302+ */
303+ return vdso_fallback_gettime(clock, ts);
304+}
305+
230306 notrace int
231307 __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
232308 {
@@ -262,3 +338,36 @@ __vdso_gettimeofday(struct timeval *tv, struct timezone *tz) · 29 unmodified lines
262338 int
263339 gettimeofday(struct timeval *, struct timezone *)
264340 __attribute__((weak, alias("__vdso_gettimeofday")));
341+
342+notrace int
343+__vdso_gettimeofday_stick(struct timeval *tv, struct timezone *tz)
344+{
345+ struct vvar_data *vvd = get_vvar_data();
346+
347+ if (likely(vvd->vclock_mode != VCLOCK_NONE)) {
348+ if (likely(tv != NULL)) {
349+ union tstv_t {
350+ struct timespec ts;
351+ struct timeval tv;
352+ } *tstv = (union tstv_t *) tv;
353+ do_realtime_stick(vvd, &tstv->ts);
354+ /*
355+ * Assign before dividing to ensure that the division is
356+ * done in the type of tv_usec, not tv_nsec.
357+ *
358+ * There cannot be > 1 billion usec in a second:
359+ * do_realtime() has already distributed such overflow
360+ * into tv_sec. So we can assign it to an int safely.
361+ */
362+ tstv->tv.tv_usec = tstv->ts.tv_nsec;
363+ tstv->tv.tv_usec /= 1000;
364+ }
365+ if (unlikely(tz != NULL)) {
366+ /* Avoid memcpy. Some old compilers fail to inline it */
367+ tz->tz_minuteswest = vvd->tz_minuteswest;
368+ tz->tz_dsttime = vvd->tz_dsttime;
369+ }
370+ return 0;
371+ }
372+ return vdso_fallback_gettimeofday(tv, tz);
373+}
arch/sparc/vdso/vdso-layout.lds.S+0−3
@@ -73,9 +73,6 @@ SECTIONS · 72 unmodified lines
7373
7474 .text : { *(.text*) } :text =0x90909090,
7575
76− .tick_patch : { *(.tick_patch) } :text
77− .tick_patch_insns : { *(.tick_patch_insns) } :text
78−
7976 /DISCARD/ : {
8077 *(.discard)
8178 *(.discard.*)
arch/sparc/vdso/vdso.lds.S+2−0
@@ -18,8 +18,10 @@ VERSION { · 17 unmodified lines
1818 global:
1919 clock_gettime;
2020 __vdso_clock_gettime;
21+ __vdso_clock_gettime_stick;
2122 gettimeofday;
2223 __vdso_gettimeofday;
24+ __vdso_gettimeofday_stick;
2325 local: *;
2426 };
2527 }
arch/sparc/vdso/vdso2c.h+1−16
@@ -17,11 +17,9 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len, · 16 unmodified lines
1717 unsigned long mapping_size;
1818 int i;
1919 unsigned long j;
20− ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr, *secstrings_hdr,
21− *patch_sec = NULL;
20+ ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr;
2221 ELF(Ehdr) *hdr = (ELF(Ehdr) *)raw_addr;
2322 ELF(Dyn) *dyn = 0, *dyn_end = 0;
24− const char *secstrings;
2523 INT_BITS syms[NSYMS] = {};
2624
2725 ELF(Phdr) *pt = (ELF(Phdr) *)(raw_addr + GET_BE(&hdr->e_phoff));
@@ -64,18 +62,11 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len, · 36 unmodified lines
6462 }
6563
6664 /* Walk the section table */
67− secstrings_hdr = raw_addr + GET_BE(&hdr->e_shoff) +
68− GET_BE(&hdr->e_shentsize)*GET_BE(&hdr->e_shstrndx);
69− secstrings = raw_addr + GET_BE(&secstrings_hdr->sh_offset);
7065 for (i = 0; i < GET_BE(&hdr->e_shnum); i++) {
7166 ELF(Shdr) *sh = raw_addr + GET_BE(&hdr->e_shoff) +
7267 GET_BE(&hdr->e_shentsize) * i;
7368 if (GET_BE(&sh->sh_type) == SHT_SYMTAB)
7469 symtab_hdr = sh;
75−
76− if (!strcmp(secstrings + GET_BE(&sh->sh_name),
77− ".tick_patch"))
78− patch_sec = sh;
7970 }
8071
8172 if (!symtab_hdr)
@@ -142,12 +133,6 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len, · 60 unmodified lines
142133 fprintf(outfile, "const struct vdso_image %s_builtin = {\n", name);
143134 fprintf(outfile, "\t.data = raw_data,\n");
144135 fprintf(outfile, "\t.size = %lu,\n", mapping_size);
145− if (patch_sec) {
146− fprintf(outfile, "\t.tick_patch = %lu,\n",
147− (unsigned long)GET_BE(&patch_sec->sh_offset));
148− fprintf(outfile, "\t.tick_patch_len = %lu,\n",
149− (unsigned long)GET_BE(&patch_sec->sh_size));
150− }
151136 for (i = 0; i < NSYMS; i++) {
152137 if (required_syms[i].export && syms[i])
153138 fprintf(outfile, "\t.sym_%s = %" PRIi64 ",\n",
arch/sparc/vdso/vdso32/vdso32.lds.S+2−0
@@ -17,8 +17,10 @@ VERSION { · 16 unmodified lines
1717 global:
1818 clock_gettime;
1919 __vdso_clock_gettime;
20+ __vdso_clock_gettime_stick;
2021 gettimeofday;
2122 __vdso_gettimeofday;
23+ __vdso_gettimeofday_stick;
2224 local: *;
2325 };
2426 }
arch/sparc/vdso/vma.c+201−21
@@ -42,24 +42,201 @@ static struct vm_special_mapping vdso_mapping32 = { · 41 unmodified lines
4242
4343 struct vvar_data *vvar_data;
4444
45−struct tick_patch_entry {
46− s32 orig, repl;
45+struct vdso_elfinfo32 {
46+ Elf32_Ehdr *hdr;
47+ Elf32_Sym *dynsym;
48+ unsigned long dynsymsize;
49+ const char *dynstr;
50+ unsigned long text;
4751 };
4852
49−static void stick_patch(const struct vdso_image *image)
53+struct vdso_elfinfo64 {
54+ Elf64_Ehdr *hdr;
55+ Elf64_Sym *dynsym;
56+ unsigned long dynsymsize;
57+ const char *dynstr;
58+ unsigned long text;
59+};
60+
61+struct vdso_elfinfo {
62+ union {
63+ struct vdso_elfinfo32 elf32;
64+ struct vdso_elfinfo64 elf64;
65+ } u;
66+};
67+
68+static void *one_section64(struct vdso_elfinfo64 *e, const char *name,
69+ unsigned long *size)
70+{
71+ const char *snames;
72+ Elf64_Shdr *shdrs;
73+ unsigned int i;
74+
75+ shdrs = (void *)e->hdr + e->hdr->e_shoff;
76+ snames = (void *)e->hdr + shdrs[e->hdr->e_shstrndx].sh_offset;
77+ for (i = 1; i < e->hdr->e_shnum; i++) {
78+ if (!strcmp(snames+shdrs[i].sh_name, name)) {
79+ if (size)
80+ *size = shdrs[i].sh_size;
81+ return (void *)e->hdr + shdrs[i].sh_offset;
82+ }
83+ }
84+ return NULL;
85+}
86+
87+static int find_sections64(const struct vdso_image *image, struct vdso_elfinfo *_e)
88+{
89+ struct vdso_elfinfo64 *e = &_e->u.elf64;
90+
91+ e->hdr = image->data;
92+ e->dynsym = one_section64(e, ".dynsym", &e->dynsymsize);
93+ e->dynstr = one_section64(e, ".dynstr", NULL);
94+
95+ if (!e->dynsym || !e->dynstr) {
96+ pr_err("VDSO64: Missing symbol sections.\n");
97+ return -ENODEV;
98+ }
99+ return 0;
100+}
101+
102+static Elf64_Sym *find_sym64(const struct vdso_elfinfo64 *e, const char *name)
103+{
104+ unsigned int i;
105+
106+ for (i = 0; i < (e->dynsymsize / sizeof(Elf64_Sym)); i++) {
107+ Elf64_Sym *s = &e->dynsym[i];
108+ if (s->st_name == 0)
109+ continue;
110+ if (!strcmp(e->dynstr + s->st_name, name))
111+ return s;
112+ }
113+ return NULL;
114+}
115+
116+static int patchsym64(struct vdso_elfinfo *_e, const char *orig,
117+ const char *new)
118+{
119+ struct vdso_elfinfo64 *e = &_e->u.elf64;
120+ Elf64_Sym *osym = find_sym64(e, orig);
121+ Elf64_Sym *nsym = find_sym64(e, new);
122+
123+ if (!nsym || !osym) {
124+ pr_err("VDSO64: Missing symbols.\n");
125+ return -ENODEV;
126+ }
127+ osym->st_value = nsym->st_value;
128+ osym->st_size = nsym->st_size;
129+ osym->st_info = nsym->st_info;
130+ osym->st_other = nsym->st_other;
131+ osym->st_shndx = nsym->st_shndx;
132+
133+ return 0;
134+}
135+
136+static void *one_section32(struct vdso_elfinfo32 *e, const char *name,
137+ unsigned long *size)
138+{
139+ const char *snames;
140+ Elf32_Shdr *shdrs;
141+ unsigned int i;
142+
143+ shdrs = (void *)e->hdr + e->hdr->e_shoff;
144+ snames = (void *)e->hdr + shdrs[e->hdr->e_shstrndx].sh_offset;
145+ for (i = 1; i < e->hdr->e_shnum; i++) {
146+ if (!strcmp(snames+shdrs[i].sh_name, name)) {
147+ if (size)
148+ *size = shdrs[i].sh_size;
149+ return (void *)e->hdr + shdrs[i].sh_offset;
150+ }
151+ }
152+ return NULL;
153+}
154+
155+static int find_sections32(const struct vdso_image *image, struct vdso_elfinfo *_e)
156+{
157+ struct vdso_elfinfo32 *e = &_e->u.elf32;
158+
159+ e->hdr = image->data;
160+ e->dynsym = one_section32(e, ".dynsym", &e->dynsymsize);
161+ e->dynstr = one_section32(e, ".dynstr", NULL);
162+
163+ if (!e->dynsym || !e->dynstr) {
164+ pr_err("VDSO32: Missing symbol sections.\n");
165+ return -ENODEV;
166+ }
167+ return 0;
168+}
169+
170+static Elf32_Sym *find_sym32(const struct vdso_elfinfo32 *e, const char *name)
50171 {
51− struct tick_patch_entry *p, *p_end;
172+ unsigned int i;
173+
174+ for (i = 0; i < (e->dynsymsize / sizeof(Elf32_Sym)); i++) {
175+ Elf32_Sym *s = &e->dynsym[i];
176+ if (s->st_name == 0)
177+ continue;
178+ if (!strcmp(e->dynstr + s->st_name, name))
179+ return s;
180+ }
181+ return NULL;
182+}
52183
53− p = image->data + image->tick_patch;
54− p_end = (void *)p + image->tick_patch_len;
55− while (p < p_end) {
56− u32 *instr = (void *)&p->orig + p->orig;
57− u32 *repl = (void *)&p->repl + p->repl;
184+static int patchsym32(struct vdso_elfinfo *_e, const char *orig,
185+ const char *new)
186+{
187+ struct vdso_elfinfo32 *e = &_e->u.elf32;
188+ Elf32_Sym *osym = find_sym32(e, orig);
189+ Elf32_Sym *nsym = find_sym32(e, new);
58190
59− *instr = *repl;
60− flushi(instr);
61− p++;
191+ if (!nsym || !osym) {
192+ pr_err("VDSO32: Missing symbols.\n");
193+ return -ENODEV;
62194 }
195+ osym->st_value = nsym->st_value;
196+ osym->st_size = nsym->st_size;
197+ osym->st_info = nsym->st_info;
198+ osym->st_other = nsym->st_other;
199+ osym->st_shndx = nsym->st_shndx;
200+
201+ return 0;
202+}
203+
204+static int find_sections(const struct vdso_image *image, struct vdso_elfinfo *e,
205+ bool elf64)
206+{
207+ if (elf64)
208+ return find_sections64(image, e);
209+ else
210+ return find_sections32(image, e);
211+}
212+
213+static int patch_one_symbol(struct vdso_elfinfo *e, const char *orig,
214+ const char *new_target, bool elf64)
215+{
216+ if (elf64)
217+ return patchsym64(e, orig, new_target);
218+ else
219+ return patchsym32(e, orig, new_target);
220+}
221+
222+static int stick_patch(const struct vdso_image *image, struct vdso_elfinfo *e, bool elf64)
223+{
224+ int err;
225+
226+ err = find_sections(image, e, elf64);
227+ if (err)
228+ return err;
229+
230+ err = patch_one_symbol(e,
231+ "__vdso_gettimeofday",
232+ "__vdso_gettimeofday_stick", elf64);
233+ if (err)
234+ return err;
235+
236+ return patch_one_symbol(e,
237+ "__vdso_clock_gettime",
238+ "__vdso_clock_gettime_stick", elf64);
239+ return 0;
63240 }
64241
65242 /*
@@ -67,13 +244,19 @@ static void stick_patch(const struct vdso_image *image) · 1 unmodified line
67244 * kernel image.
68245 */
69246 int __init init_vdso_image(const struct vdso_image *image,
70− struct vm_special_mapping *vdso_mapping)
247+ struct vm_special_mapping *vdso_mapping, bool elf64)
71248 {
72− int i;
249+ int cnpages = (image->size) / PAGE_SIZE;
73250 struct page *dp, **dpp = NULL;
74− int dnpages = 0;
75251 struct page *cp, **cpp = NULL;
76− int cnpages = (image->size) / PAGE_SIZE;
252+ struct vdso_elfinfo ei;
253+ int i, dnpages = 0;
254+
255+ if (tlb_type != spitfire) {
256+ int err = stick_patch(image, &ei, elf64);
257+ if (err)
258+ return err;
259+ }
77260
78261 /*
79262 * First, the vdso text. This is initialied data, an integral number of
@@ -88,9 +271,6 @@ int __init init_vdso_image(const struct vdso_image *image, · 8 unmodified lines
88271 if (!cpp)
89272 goto oom;
90273
91− if (tlb_type != spitfire)
92− stick_patch(image);
93−
94274 for (i = 0; i < cnpages; i++) {
95275 cp = alloc_page(GFP_KERNEL);
96276 if (!cp)
@@ -153,13 +333,13 @@ static int __init init_vdso(void) · 56 unmodified lines
153333 {
154334 int err = 0;
155335 #ifdef CONFIG_SPARC64
156− err = init_vdso_image(&vdso_image_64_builtin, &vdso_mapping64);
336+ err = init_vdso_image(&vdso_image_64_builtin, &vdso_mapping64, true);
157337 if (err)
158338 return err;
159339 #endif
160340
161341 #ifdef CONFIG_COMPAT
162− err = init_vdso_image(&vdso_image_32_builtin, &vdso_mapping32);
342+ err = init_vdso_image(&vdso_image_32_builtin, &vdso_mapping32, false);
163343 #endif
164344 return err;
165345

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t