Skip to content

Commit e5f6d9a

Browse files
committed
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.
2 parents c300af2 + caf539c commit e5f6d9a

File tree

7 files changed

+335
-62
lines changed

7 files changed

+335
-62
lines changed

arch/sparc/include/asm/vdso.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ struct vdso_image {
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

Lines changed: 129 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -90,33 +90,34 @@ notrace static __always_inline u64 vread_tick(void)
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
106105
notrace static __always_inline u64 vread_tick(void)
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)
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,
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,
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
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)
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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,6 @@ SECTIONS
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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@ VERSION {
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

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,9 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
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,
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,
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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,10 @@ VERSION {
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
}

0 commit comments

Comments
 (0)