-
-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
riscv: use vDSO common flow to reduce the latency of the time-related…
… functions Even if RISC-V has supported the vDSO feature, the latency of the functions for obtaining the system time is still expensive. It is because these functions still trigger a corresponding system call in the process, which slows down the response time. If we want to remove the system call to reduce the latency, the kernel should have the ability to output the system clock information to userspace. This patch introduces the vDSO common flow to enable the kernel to achieve the above feature and uses "rdtime" instruction to obtain the current time in the user space. Under this condition, the latency cost by the ecall from U-mode to S-mode can be eliminated. After applying this patch, the latency of gettimeofday() measured on the HiFive unleashed board can be reduced by %61. Signed-off-by: Vincent Chen <[email protected]> Reviewed-by: Atish Patra <[email protected]> Signed-off-by: Palmer Dabbelt <[email protected]>
- Loading branch information
1 parent
05589dd
commit ad5d112
Showing
16 changed files
with
199 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
#ifndef _ASM_CLOCKSOURCE_H | ||
#define _ASM_CLOCKSOURCE_H | ||
|
||
#include <asm/vdso/clocksource.h> | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
#ifndef __ASM_VDSOCLOCKSOURCE_H | ||
#define __ASM_VDSOCLOCKSOURCE_H | ||
|
||
#define VDSO_ARCH_CLOCKMODES \ | ||
VDSO_CLOCKMODE_ARCHTIMER | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
#ifndef __ASM_VDSO_GETTIMEOFDAY_H | ||
#define __ASM_VDSO_GETTIMEOFDAY_H | ||
|
||
#ifndef __ASSEMBLY__ | ||
|
||
#include <asm/unistd.h> | ||
#include <asm/csr.h> | ||
#include <uapi/linux/time.h> | ||
|
||
#define VDSO_HAS_CLOCK_GETRES 1 | ||
|
||
static __always_inline | ||
int gettimeofday_fallback(struct __kernel_old_timeval *_tv, | ||
struct timezone *_tz) | ||
{ | ||
register struct __kernel_old_timeval *tv asm("a0") = _tv; | ||
register struct timezone *tz asm("a1") = _tz; | ||
register long ret asm("a0"); | ||
register long nr asm("a7") = __NR_gettimeofday; | ||
|
||
asm volatile ("ecall\n" | ||
: "=r" (ret) | ||
: "r"(tv), "r"(tz), "r"(nr) | ||
: "memory"); | ||
|
||
return ret; | ||
} | ||
|
||
static __always_inline | ||
long clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) | ||
{ | ||
register clockid_t clkid asm("a0") = _clkid; | ||
register struct __kernel_timespec *ts asm("a1") = _ts; | ||
register long ret asm("a0"); | ||
register long nr asm("a7") = __NR_clock_gettime; | ||
|
||
asm volatile ("ecall\n" | ||
: "=r" (ret) | ||
: "r"(clkid), "r"(ts), "r"(nr) | ||
: "memory"); | ||
|
||
return ret; | ||
} | ||
|
||
static __always_inline | ||
int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts) | ||
{ | ||
register clockid_t clkid asm("a0") = _clkid; | ||
register struct __kernel_timespec *ts asm("a1") = _ts; | ||
register long ret asm("a0"); | ||
register long nr asm("a7") = __NR_clock_getres; | ||
|
||
asm volatile ("ecall\n" | ||
: "=r" (ret) | ||
: "r"(clkid), "r"(ts), "r"(nr) | ||
: "memory"); | ||
|
||
return ret; | ||
} | ||
|
||
static __always_inline u64 __arch_get_hw_counter(s32 clock_mode) | ||
{ | ||
/* | ||
* The purpose of csr_read(CSR_TIME) is to trap the system into | ||
* M-mode to obtain the value of CSR_TIME. Hence, unlike other | ||
* architecture, no fence instructions surround the csr_read() | ||
*/ | ||
return csr_read(CSR_TIME); | ||
} | ||
|
||
static __always_inline const struct vdso_data *__arch_get_vdso_data(void) | ||
{ | ||
return _vdso_data; | ||
} | ||
|
||
#endif /* !__ASSEMBLY__ */ | ||
|
||
#endif /* __ASM_VDSO_GETTIMEOFDAY_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
/* SPDX-License-Identifier: GPL-2.0-only */ | ||
#ifndef __ASM_VDSO_PROCESSOR_H | ||
#define __ASM_VDSO_PROCESSOR_H | ||
|
||
#ifndef __ASSEMBLY__ | ||
|
||
static inline void cpu_relax(void) | ||
{ | ||
#ifdef __riscv_muldiv | ||
int dummy; | ||
/* In lieu of a halt instruction, induce a long-latency stall. */ | ||
__asm__ __volatile__ ("div %0, %0, zero" : "=r" (dummy)); | ||
#endif | ||
barrier(); | ||
} | ||
|
||
#endif /* __ASSEMBLY__ */ | ||
|
||
#endif /* __ASM_VDSO_PROCESSOR_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* SPDX-License-Identifier: GPL-2.0 */ | ||
#ifndef __ASM_VDSO_VSYSCALL_H | ||
#define __ASM_VDSO_VSYSCALL_H | ||
|
||
#ifndef __ASSEMBLY__ | ||
|
||
#include <linux/timekeeper_internal.h> | ||
#include <vdso/datapage.h> | ||
|
||
extern struct vdso_data *vdso_data; | ||
|
||
/* | ||
* Update the vDSO data page to keep in sync with kernel timekeeping. | ||
*/ | ||
static __always_inline struct vdso_data *__riscv_get_k_vdso_data(void) | ||
{ | ||
return vdso_data; | ||
} | ||
|
||
#define __arch_get_k_vdso_data __riscv_get_k_vdso_data | ||
|
||
/* The asm-generic header needs to be included after the definitions above */ | ||
#include <asm-generic/vdso/vsyscall.h> | ||
|
||
#endif /* !__ASSEMBLY__ */ | ||
|
||
#endif /* __ASM_VDSO_VSYSCALL_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* | ||
* Copied from arch/arm64/kernel/vdso/vgettimeofday.c | ||
* | ||
* Copyright (C) 2018 ARM Ltd. | ||
* Copyright (C) 2020 SiFive | ||
*/ | ||
|
||
#include <linux/time.h> | ||
#include <linux/types.h> | ||
|
||
int __vdso_clock_gettime(clockid_t clock, struct __kernel_timespec *ts) | ||
{ | ||
return __cvdso_clock_gettime(clock, ts); | ||
} | ||
|
||
int __vdso_gettimeofday(struct __kernel_old_timeval *tv, struct timezone *tz) | ||
{ | ||
return __cvdso_gettimeofday(tv, tz); | ||
} | ||
|
||
int __vdso_clock_getres(clockid_t clock_id, struct __kernel_timespec *res) | ||
{ | ||
return __cvdso_clock_getres(clock_id, res); | ||
} |