Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Linus Torvalds committed Oct 26, 2018
2 parents c300af2 + caf539c commit e5f6d9a
Show file tree
Hide file tree
Showing 7 changed files with 335 additions and 62 deletions.
2 changes: 0 additions & 2 deletions arch/sparc/include/asm/vdso.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ struct vdso_image {
void *data;
unsigned long size; /* Always a multiple of PAGE_SIZE */

unsigned long tick_patch, tick_patch_len;

long sym_vvar_start; /* Negative offset to the vvar area */
};

Expand Down
149 changes: 129 additions & 20 deletions arch/sparc/vdso/vclock_gettime.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,33 +90,34 @@ notrace static __always_inline u64 vread_tick(void)
{
u64 ret;

__asm__ __volatile__("1:\n\t"
"rd %%tick, %0\n\t"
".pushsection .tick_patch, \"a\"\n\t"
".word 1b - ., 1f - .\n\t"
".popsection\n\t"
".pushsection .tick_patch_replacement, \"ax\"\n\t"
"1:\n\t"
"rd %%asr24, %0\n\t"
".popsection\n"
: "=r" (ret));
__asm__ __volatile__("rd %%tick, %0" : "=r" (ret));
return ret;
}

notrace static __always_inline u64 vread_tick_stick(void)
{
u64 ret;

__asm__ __volatile__("rd %%asr24, %0" : "=r" (ret));
return ret;
}
#else
notrace static __always_inline u64 vread_tick(void)
{
register unsigned long long ret asm("o4");

__asm__ __volatile__("1:\n\t"
"rd %%tick, %L0\n\t"
"srlx %L0, 32, %H0\n\t"
".pushsection .tick_patch, \"a\"\n\t"
".word 1b - ., 1f - .\n\t"
".popsection\n\t"
".pushsection .tick_patch_replacement, \"ax\"\n\t"
"1:\n\t"
"rd %%asr24, %L0\n\t"
".popsection\n"
__asm__ __volatile__("rd %%tick, %L0\n\t"
"srlx %L0, 32, %H0"
: "=r" (ret));
return ret;
}

notrace static __always_inline u64 vread_tick_stick(void)
{
register unsigned long long ret asm("o4");

__asm__ __volatile__("rd %%asr24, %L0\n\t"
"srlx %L0, 32, %H0"
: "=r" (ret));
return ret;
}
Expand All @@ -132,6 +133,16 @@ notrace static __always_inline u64 vgetsns(struct vvar_data *vvar)
return v * vvar->clock.mult;
}

notrace static __always_inline u64 vgetsns_stick(struct vvar_data *vvar)
{
u64 v;
u64 cycles;

cycles = vread_tick_stick();
v = (cycles - vvar->clock.cycle_last) & vvar->clock.mask;
return v * vvar->clock.mult;
}

notrace static __always_inline int do_realtime(struct vvar_data *vvar,
struct timespec *ts)
{
Expand All @@ -152,6 +163,26 @@ notrace static __always_inline int do_realtime(struct vvar_data *vvar,
return 0;
}

notrace static __always_inline int do_realtime_stick(struct vvar_data *vvar,
struct timespec *ts)
{
unsigned long seq;
u64 ns;

do {
seq = vvar_read_begin(vvar);
ts->tv_sec = vvar->wall_time_sec;
ns = vvar->wall_time_snsec;
ns += vgetsns_stick(vvar);
ns >>= vvar->clock.shift;
} while (unlikely(vvar_read_retry(vvar, seq)));

ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
ts->tv_nsec = ns;

return 0;
}

notrace static __always_inline int do_monotonic(struct vvar_data *vvar,
struct timespec *ts)
{
Expand All @@ -172,6 +203,26 @@ notrace static __always_inline int do_monotonic(struct vvar_data *vvar,
return 0;
}

notrace static __always_inline int do_monotonic_stick(struct vvar_data *vvar,
struct timespec *ts)
{
unsigned long seq;
u64 ns;

do {
seq = vvar_read_begin(vvar);
ts->tv_sec = vvar->monotonic_time_sec;
ns = vvar->monotonic_time_snsec;
ns += vgetsns_stick(vvar);
ns >>= vvar->clock.shift;
} while (unlikely(vvar_read_retry(vvar, seq)));

ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
ts->tv_nsec = ns;

return 0;
}

notrace static int do_realtime_coarse(struct vvar_data *vvar,
struct timespec *ts)
{
Expand Down Expand Up @@ -227,6 +278,31 @@ int
clock_gettime(clockid_t, struct timespec *)
__attribute__((weak, alias("__vdso_clock_gettime")));

notrace int
__vdso_clock_gettime_stick(clockid_t clock, struct timespec *ts)
{
struct vvar_data *vvd = get_vvar_data();

switch (clock) {
case CLOCK_REALTIME:
if (unlikely(vvd->vclock_mode == VCLOCK_NONE))
break;
return do_realtime_stick(vvd, ts);
case CLOCK_MONOTONIC:
if (unlikely(vvd->vclock_mode == VCLOCK_NONE))
break;
return do_monotonic_stick(vvd, ts);
case CLOCK_REALTIME_COARSE:
return do_realtime_coarse(vvd, ts);
case CLOCK_MONOTONIC_COARSE:
return do_monotonic_coarse(vvd, ts);
}
/*
* Unknown clock ID ? Fall back to the syscall.
*/
return vdso_fallback_gettime(clock, ts);
}

notrace int
__vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
{
Expand Down Expand Up @@ -262,3 +338,36 @@ __vdso_gettimeofday(struct timeval *tv, struct timezone *tz)
int
gettimeofday(struct timeval *, struct timezone *)
__attribute__((weak, alias("__vdso_gettimeofday")));

notrace int
__vdso_gettimeofday_stick(struct timeval *tv, struct timezone *tz)
{
struct vvar_data *vvd = get_vvar_data();

if (likely(vvd->vclock_mode != VCLOCK_NONE)) {
if (likely(tv != NULL)) {
union tstv_t {
struct timespec ts;
struct timeval tv;
} *tstv = (union tstv_t *) tv;
do_realtime_stick(vvd, &tstv->ts);
/*
* Assign before dividing to ensure that the division is
* done in the type of tv_usec, not tv_nsec.
*
* There cannot be > 1 billion usec in a second:
* do_realtime() has already distributed such overflow
* into tv_sec. So we can assign it to an int safely.
*/
tstv->tv.tv_usec = tstv->ts.tv_nsec;
tstv->tv.tv_usec /= 1000;
}
if (unlikely(tz != NULL)) {
/* Avoid memcpy. Some old compilers fail to inline it */
tz->tz_minuteswest = vvd->tz_minuteswest;
tz->tz_dsttime = vvd->tz_dsttime;
}
return 0;
}
return vdso_fallback_gettimeofday(tv, tz);
}
3 changes: 0 additions & 3 deletions arch/sparc/vdso/vdso-layout.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,6 @@ SECTIONS

.text : { *(.text*) } :text =0x90909090,

.tick_patch : { *(.tick_patch) } :text
.tick_patch_insns : { *(.tick_patch_insns) } :text

/DISCARD/ : {
*(.discard)
*(.discard.*)
Expand Down
2 changes: 2 additions & 0 deletions arch/sparc/vdso/vdso.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ VERSION {
global:
clock_gettime;
__vdso_clock_gettime;
__vdso_clock_gettime_stick;
gettimeofday;
__vdso_gettimeofday;
__vdso_gettimeofday_stick;
local: *;
};
}
17 changes: 1 addition & 16 deletions arch/sparc/vdso/vdso2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
unsigned long mapping_size;
int i;
unsigned long j;
ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr, *secstrings_hdr,
*patch_sec = NULL;
ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr;
ELF(Ehdr) *hdr = (ELF(Ehdr) *)raw_addr;
ELF(Dyn) *dyn = 0, *dyn_end = 0;
const char *secstrings;
INT_BITS syms[NSYMS] = {};

ELF(Phdr) *pt = (ELF(Phdr) *)(raw_addr + GET_BE(&hdr->e_phoff));
Expand Down Expand Up @@ -64,18 +62,11 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
}

/* Walk the section table */
secstrings_hdr = raw_addr + GET_BE(&hdr->e_shoff) +
GET_BE(&hdr->e_shentsize)*GET_BE(&hdr->e_shstrndx);
secstrings = raw_addr + GET_BE(&secstrings_hdr->sh_offset);
for (i = 0; i < GET_BE(&hdr->e_shnum); i++) {
ELF(Shdr) *sh = raw_addr + GET_BE(&hdr->e_shoff) +
GET_BE(&hdr->e_shentsize) * i;
if (GET_BE(&sh->sh_type) == SHT_SYMTAB)
symtab_hdr = sh;

if (!strcmp(secstrings + GET_BE(&sh->sh_name),
".tick_patch"))
patch_sec = sh;
}

if (!symtab_hdr)
Expand Down Expand Up @@ -142,12 +133,6 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
fprintf(outfile, "const struct vdso_image %s_builtin = {\n", name);
fprintf(outfile, "\t.data = raw_data,\n");
fprintf(outfile, "\t.size = %lu,\n", mapping_size);
if (patch_sec) {
fprintf(outfile, "\t.tick_patch = %lu,\n",
(unsigned long)GET_BE(&patch_sec->sh_offset));
fprintf(outfile, "\t.tick_patch_len = %lu,\n",
(unsigned long)GET_BE(&patch_sec->sh_size));
}
for (i = 0; i < NSYMS; i++) {
if (required_syms[i].export && syms[i])
fprintf(outfile, "\t.sym_%s = %" PRIi64 ",\n",
Expand Down
2 changes: 2 additions & 0 deletions arch/sparc/vdso/vdso32/vdso32.lds.S
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@ VERSION {
global:
clock_gettime;
__vdso_clock_gettime;
__vdso_clock_gettime_stick;
gettimeofday;
__vdso_gettimeofday;
__vdso_gettimeofday_stick;
local: *;
};
}
Loading

0 comments on commit e5f6d9a

Please sign in to comment.