android_kernel_xiaomi_sm8350/arch/mips/include/asm/vdso/gettimeofday.h
Romain Naour 91b08c5319 mips: Do not include hi and lo in clobber list for R6
commit 1d7ba0165d8206ac073f7ac3b14fc0836b66eae7 upstream.

From [1]
"GCC 10 (PR 91233) won't silently allow registers that are not
architecturally available to be present in the clobber list anymore,
resulting in build failure for mips*r6 targets in form of:
...
.../sysdep.h:146:2: error: the register ‘lo’ cannot be clobbered in ‘asm’ for the current target
  146 |  __asm__ volatile (      \
      |  ^~~~~~~

This is because base R6 ISA doesn't define hi and lo registers w/o DSP
extension. This patch provides the alternative clobber list for r6 targets
that won't include those registers."

Since kernel 5.4 and mips support for generic vDSO [2], the kernel fail to
build for mips r6 cpus with gcc 10 for the same reason as glibc.

[1] https://sourceware.org/git/?p=glibc.git;a=commit;h=020b2a97bb15f807c0482f0faee2184ed05bcad8
[2] '24640f233b46 ("mips: Add support for generic vDSO")'

Signed-off-by: Romain Naour <romain.naour@gmail.com>
Signed-off-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com>
Signed-off-by: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2021-05-07 10:51:36 +02:00

228 lines
5.1 KiB
C

/*
* Copyright (C) 2018 ARM Limited
* Copyright (C) 2015 Imagination Technologies
* Author: Alex Smith <alex.smith@imgtec.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#ifndef __ASM_VDSO_GETTIMEOFDAY_H
#define __ASM_VDSO_GETTIMEOFDAY_H
#ifndef __ASSEMBLY__
#include <linux/compiler.h>
#include <linux/time.h>
#include <asm/vdso/vdso.h>
#include <asm/clocksource.h>
#include <asm/io.h>
#include <asm/unistd.h>
#include <asm/vdso.h>
#define VDSO_HAS_CLOCK_GETRES 1
#define __VDSO_USE_SYSCALL ULLONG_MAX
#if MIPS_ISA_REV < 6
#define VDSO_SYSCALL_CLOBBERS "hi", "lo",
#else
#define VDSO_SYSCALL_CLOBBERS
#endif
static __always_inline long gettimeofday_fallback(
struct __kernel_old_timeval *_tv,
struct timezone *_tz)
{
register struct timezone *tz asm("a1") = _tz;
register struct __kernel_old_timeval *tv asm("a0") = _tv;
register long ret asm("v0");
register long nr asm("v0") = __NR_gettimeofday;
register long error asm("a3");
asm volatile(
" syscall\n"
: "=r" (ret), "=r" (error)
: "r" (tv), "r" (tz), "r" (nr)
: "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
"$14", "$15", "$24", "$25",
VDSO_SYSCALL_CLOBBERS
"memory");
return error ? -ret : ret;
}
static __always_inline long clock_gettime_fallback(
clockid_t _clkid,
struct __kernel_timespec *_ts)
{
register struct __kernel_timespec *ts asm("a1") = _ts;
register clockid_t clkid asm("a0") = _clkid;
register long ret asm("v0");
#if _MIPS_SIM == _MIPS_SIM_ABI64
register long nr asm("v0") = __NR_clock_gettime;
#else
register long nr asm("v0") = __NR_clock_gettime64;
#endif
register long error asm("a3");
asm volatile(
" syscall\n"
: "=r" (ret), "=r" (error)
: "r" (clkid), "r" (ts), "r" (nr)
: "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
"$14", "$15", "$24", "$25",
VDSO_SYSCALL_CLOBBERS
"memory");
return error ? -ret : ret;
}
static __always_inline int clock_getres_fallback(
clockid_t _clkid,
struct __kernel_timespec *_ts)
{
register struct __kernel_timespec *ts asm("a1") = _ts;
register clockid_t clkid asm("a0") = _clkid;
register long ret asm("v0");
#if _MIPS_SIM == _MIPS_SIM_ABI64
register long nr asm("v0") = __NR_clock_getres;
#else
register long nr asm("v0") = __NR_clock_getres_time64;
#endif
register long error asm("a3");
asm volatile(
" syscall\n"
: "=r" (ret), "=r" (error)
: "r" (clkid), "r" (ts), "r" (nr)
: "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
"$14", "$15", "$24", "$25",
VDSO_SYSCALL_CLOBBERS
"memory");
return error ? -ret : ret;
}
#if _MIPS_SIM != _MIPS_SIM_ABI64
#define VDSO_HAS_32BIT_FALLBACK 1
static __always_inline long clock_gettime32_fallback(
clockid_t _clkid,
struct old_timespec32 *_ts)
{
register struct old_timespec32 *ts asm("a1") = _ts;
register clockid_t clkid asm("a0") = _clkid;
register long ret asm("v0");
register long nr asm("v0") = __NR_clock_gettime;
register long error asm("a3");
asm volatile(
" syscall\n"
: "=r" (ret), "=r" (error)
: "r" (clkid), "r" (ts), "r" (nr)
: "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
"$14", "$15", "$24", "$25",
VDSO_SYSCALL_CLOBBERS
"memory");
return error ? -ret : ret;
}
static __always_inline int clock_getres32_fallback(
clockid_t _clkid,
struct old_timespec32 *_ts)
{
register struct old_timespec32 *ts asm("a1") = _ts;
register clockid_t clkid asm("a0") = _clkid;
register long ret asm("v0");
register long nr asm("v0") = __NR_clock_getres;
register long error asm("a3");
asm volatile(
" syscall\n"
: "=r" (ret), "=r" (error)
: "r" (clkid), "r" (ts), "r" (nr)
: "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
"$14", "$15", "$24", "$25",
VDSO_SYSCALL_CLOBBERS
"memory");
return error ? -ret : ret;
}
#endif
#ifdef CONFIG_CSRC_R4K
static __always_inline u64 read_r4k_count(void)
{
unsigned int count;
__asm__ __volatile__(
" .set push\n"
" .set mips32r2\n"
" rdhwr %0, $2\n"
" .set pop\n"
: "=r" (count));
return count;
}
#endif
#ifdef CONFIG_CLKSRC_MIPS_GIC
static __always_inline u64 read_gic_count(const struct vdso_data *data)
{
void __iomem *gic = get_gic(data);
u32 hi, hi2, lo;
do {
hi = __raw_readl(gic + sizeof(lo));
lo = __raw_readl(gic);
hi2 = __raw_readl(gic + sizeof(lo));
} while (hi2 != hi);
return (((u64)hi) << 32) + lo;
}
#endif
static __always_inline u64 __arch_get_hw_counter(s32 clock_mode)
{
#ifdef CONFIG_CLKSRC_MIPS_GIC
const struct vdso_data *data = get_vdso_data();
#endif
u64 cycle_now;
switch (clock_mode) {
#ifdef CONFIG_CSRC_R4K
case VDSO_CLOCK_R4K:
cycle_now = read_r4k_count();
break;
#endif
#ifdef CONFIG_CLKSRC_MIPS_GIC
case VDSO_CLOCK_GIC:
cycle_now = read_gic_count(data);
break;
#endif
default:
cycle_now = __VDSO_USE_SYSCALL;
break;
}
return cycle_now;
}
static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
{
return get_vdso_data();
}
#endif /* !__ASSEMBLY__ */
#endif /* __ASM_VDSO_GETTIMEOFDAY_H */