Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e5f6d9af authored by Linus Torvalds's avatar Linus Torvalds
Browse files
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.
parents c300af28 caf539cd
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -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 */
};

+129 −20
Original line number Diff line number Diff line
@@ -90,16 +90,15 @@ 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
@@ -107,16 +106,18 @@ 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;
}
@@ -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)
{
@@ -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)
{
@@ -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)
{
@@ -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)
{
@@ -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);
}
+0 −3
Original line number Diff line number Diff line
@@ -73,9 +73,6 @@ SECTIONS

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

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

	/DISCARD/ : {
		*(.discard)
		*(.discard.*)
+2 −0
Original line number Diff line number Diff line
@@ -18,8 +18,10 @@ VERSION {
	global:
		clock_gettime;
		__vdso_clock_gettime;
		__vdso_clock_gettime_stick;
		gettimeofday;
		__vdso_gettimeofday;
		__vdso_gettimeofday_stick;
	local: *;
	};
}
+1 −16
Original line number Diff line number Diff line
@@ -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));
@@ -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)
@@ -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",
Loading