forked from beagleboard/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
x86, vdso: Add 32 bit VDSO time support for 64 bit kernel
This patch add the VDSO time support for the IA32 Emulation Layer. Due the nature of the kernel headers and the LP64 compiler where the size of a long and a pointer differs against a 32 bit compiler, there is some type hacking necessary for optimal performance. The vsyscall_gtod_data struture must be a rearranged to serve 32- and 64-bit code access at the same time: - The seqcount_t was replaced by an unsigned, this makes the vsyscall_gtod_data intedepend of kernel configuration and internal functions. - All kernel internal structures are replaced by fix size elements which works for 32- and 64-bit access - The inner struct clock was removed to pack the whole struct. The "unsigned seq" would be handled by functions derivated from seqcount_t. Signed-off-by: Stefani Seibold <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: H. Peter Anvin <[email protected]>
- Loading branch information
Showing
5 changed files
with
155 additions
and
67 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,30 +1,73 @@ | ||
#ifndef _ASM_X86_VGTOD_H | ||
#define _ASM_X86_VGTOD_H | ||
|
||
#include <asm/vsyscall.h> | ||
#include <linux/compiler.h> | ||
#include <linux/clocksource.h> | ||
|
||
#ifdef BUILD_VDSO32_64 | ||
typedef u64 gtod_long_t; | ||
#else | ||
typedef unsigned long gtod_long_t; | ||
#endif | ||
/* | ||
* vsyscall_gtod_data will be accessed by 32 and 64 bit code at the same time | ||
* so be carefull by modifying this structure. | ||
*/ | ||
struct vsyscall_gtod_data { | ||
seqcount_t seq; | ||
unsigned seq; | ||
|
||
struct { /* extract of a clocksource struct */ | ||
int vclock_mode; | ||
cycle_t cycle_last; | ||
cycle_t mask; | ||
u32 mult; | ||
u32 shift; | ||
} clock; | ||
int vclock_mode; | ||
cycle_t cycle_last; | ||
cycle_t mask; | ||
u32 mult; | ||
u32 shift; | ||
|
||
/* open coded 'struct timespec' */ | ||
time_t wall_time_sec; | ||
u64 wall_time_snsec; | ||
gtod_long_t wall_time_sec; | ||
gtod_long_t monotonic_time_sec; | ||
u64 monotonic_time_snsec; | ||
time_t monotonic_time_sec; | ||
gtod_long_t wall_time_coarse_sec; | ||
gtod_long_t wall_time_coarse_nsec; | ||
gtod_long_t monotonic_time_coarse_sec; | ||
gtod_long_t monotonic_time_coarse_nsec; | ||
|
||
struct timezone sys_tz; | ||
struct timespec wall_time_coarse; | ||
struct timespec monotonic_time_coarse; | ||
int tz_minuteswest; | ||
int tz_dsttime; | ||
}; | ||
extern struct vsyscall_gtod_data vsyscall_gtod_data; | ||
|
||
static inline unsigned gtod_read_begin(const struct vsyscall_gtod_data *s) | ||
{ | ||
unsigned ret; | ||
|
||
repeat: | ||
ret = ACCESS_ONCE(s->seq); | ||
if (unlikely(ret & 1)) { | ||
cpu_relax(); | ||
goto repeat; | ||
} | ||
smp_rmb(); | ||
return ret; | ||
} | ||
|
||
static inline int gtod_read_retry(const struct vsyscall_gtod_data *s, | ||
unsigned start) | ||
{ | ||
smp_rmb(); | ||
return unlikely(s->seq != start); | ||
} | ||
|
||
static inline void gtod_write_begin(struct vsyscall_gtod_data *s) | ||
{ | ||
++s->seq; | ||
smp_wmb(); | ||
} | ||
|
||
static inline void gtod_write_end(struct vsyscall_gtod_data *s) | ||
{ | ||
smp_wmb(); | ||
++s->seq; | ||
} | ||
|
||
#endif /* _ASM_X86_VGTOD_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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
* | ||
* Modified for x86 32 bit architecture by | ||
* Stefani Seibold <[email protected]> | ||
* sponsored by Rohde & Schwarz GmbH & Co. KG Munich/Germany | ||
* | ||
* Thanks to [email protected] for some useful hint. | ||
* Special thanks to Ingo Molnar for his early experience with | ||
|
@@ -13,26 +14,28 @@ | |
|
||
#include <linux/timekeeper_internal.h> | ||
#include <asm/vgtod.h> | ||
#include <asm/vvar.h> | ||
|
||
DEFINE_VVAR(struct vsyscall_gtod_data, vsyscall_gtod_data); | ||
|
||
void update_vsyscall_tz(void) | ||
{ | ||
vsyscall_gtod_data.sys_tz = sys_tz; | ||
vsyscall_gtod_data.tz_minuteswest = sys_tz.tz_minuteswest; | ||
vsyscall_gtod_data.tz_dsttime = sys_tz.tz_dsttime; | ||
} | ||
|
||
void update_vsyscall(struct timekeeper *tk) | ||
{ | ||
struct vsyscall_gtod_data *vdata = &vsyscall_gtod_data; | ||
|
||
write_seqcount_begin(&vdata->seq); | ||
gtod_write_begin(vdata); | ||
|
||
/* copy vsyscall data */ | ||
vdata->clock.vclock_mode = tk->clock->archdata.vclock_mode; | ||
vdata->clock.cycle_last = tk->clock->cycle_last; | ||
vdata->clock.mask = tk->clock->mask; | ||
vdata->clock.mult = tk->mult; | ||
vdata->clock.shift = tk->shift; | ||
vdata->vclock_mode = tk->clock->archdata.vclock_mode; | ||
vdata->cycle_last = tk->clock->cycle_last; | ||
vdata->mask = tk->clock->mask; | ||
vdata->mult = tk->mult; | ||
vdata->shift = tk->shift; | ||
|
||
vdata->wall_time_sec = tk->xtime_sec; | ||
vdata->wall_time_snsec = tk->xtime_nsec; | ||
|
@@ -49,11 +52,18 @@ void update_vsyscall(struct timekeeper *tk) | |
vdata->monotonic_time_sec++; | ||
} | ||
|
||
vdata->wall_time_coarse.tv_sec = tk->xtime_sec; | ||
vdata->wall_time_coarse.tv_nsec = (long)(tk->xtime_nsec >> tk->shift); | ||
vdata->wall_time_coarse_sec = tk->xtime_sec; | ||
vdata->wall_time_coarse_nsec = (long)(tk->xtime_nsec >> tk->shift); | ||
|
||
vdata->monotonic_time_coarse = timespec_add(vdata->wall_time_coarse, | ||
tk->wall_to_monotonic); | ||
vdata->monotonic_time_coarse_sec = | ||
vdata->wall_time_coarse_sec + tk->wall_to_monotonic.tv_sec; | ||
vdata->monotonic_time_coarse_nsec = | ||
vdata->wall_time_coarse_nsec + tk->wall_to_monotonic.tv_nsec; | ||
|
||
write_seqcount_end(&vdata->seq); | ||
while (vdata->monotonic_time_coarse_nsec >= NSEC_PER_SEC) { | ||
vdata->monotonic_time_coarse_nsec -= NSEC_PER_SEC; | ||
vdata->monotonic_time_coarse_sec++; | ||
} | ||
|
||
gtod_write_end(vdata); | ||
} |
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