mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-21 03:33:59 +08:00
s390/time: convert tod_clock_base to union
Convert tod_clock_base to union tod_clock. This simplifies quite a bit of code and also fixes a bug in read_persistent_clock64(); void read_persistent_clock64(struct timespec64 *ts) { __u64 delta; delta = initial_leap_seconds + TOD_UNIX_EPOCH; get_tod_clock_ext(clk); *(__u64 *) &clk[1] -= delta; if (*(__u64 *) &clk[1] > delta) clk[0]--; ext_to_timespec64(clk, ts); } Assume &clk[1] == 3 and delta == 2; then after the substraction the if condition becomes true and the epoch part of the clock is decremented by one because of an assumed overflow, even though there is none. Fix this by using 128 bit arithmetics and let the compiler do the right thing: void read_persistent_clock64(struct timespec64 *ts) { union tod_clock clk; u64 delta; delta = initial_leap_seconds + TOD_UNIX_EPOCH; store_tod_clock_ext(&clk); clk.eitod -= delta; ext_to_timespec64(&clk, ts); } Signed-off-by: Heiko Carstens <hca@linux.ibm.com> Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
parent
cc2c7db28f
commit
f8d8977a3d
@ -208,7 +208,7 @@ static inline cycles_t get_cycles(void)
|
||||
int get_phys_clock(unsigned long *clock);
|
||||
void init_cpu_timer(void);
|
||||
|
||||
extern unsigned char tod_clock_base[16] __aligned(8);
|
||||
extern union tod_clock tod_clock_base;
|
||||
|
||||
/**
|
||||
* get_clock_monotonic - returns current time in clock rate units
|
||||
@ -222,7 +222,7 @@ static inline unsigned long long get_tod_clock_monotonic(void)
|
||||
unsigned long long tod;
|
||||
|
||||
preempt_disable_notrace();
|
||||
tod = get_tod_clock() - *(unsigned long long *) &tod_clock_base[1];
|
||||
tod = get_tod_clock() - tod_clock_base.tod;
|
||||
preempt_enable_notrace();
|
||||
return tod;
|
||||
}
|
||||
|
@ -43,8 +43,8 @@ static void __init reset_tod_clock(void)
|
||||
if (set_tod_clock(TOD_UNIX_EPOCH) || store_tod_clock_ext_cc(&clk))
|
||||
disabled_wait();
|
||||
|
||||
memset(tod_clock_base, 0, 16);
|
||||
*(__u64 *) &tod_clock_base[1] = TOD_UNIX_EPOCH;
|
||||
memset(&tod_clock_base, 0, sizeof(tod_clock_base));
|
||||
tod_clock_base.tod = TOD_UNIX_EPOCH;
|
||||
S390_lowcore.last_update_clock = TOD_UNIX_EPOCH;
|
||||
}
|
||||
|
||||
@ -230,7 +230,7 @@ static __init void detect_machine_facilities(void)
|
||||
}
|
||||
if (test_facility(133))
|
||||
S390_lowcore.machine_flags |= MACHINE_FLAG_GS;
|
||||
if (test_facility(139) && (tod_clock_base[1] & 0x80)) {
|
||||
if (test_facility(139) && (tod_clock_base.tod >> 63)) {
|
||||
/* Enabled signed clock comparator comparisons */
|
||||
S390_lowcore.machine_flags |= MACHINE_FLAG_SCC;
|
||||
clock_comparator_max = -1ULL >> 1;
|
||||
|
@ -118,7 +118,7 @@ static void cf_diag_trailer(struct cf_trailer_entry *te)
|
||||
if (te->cpu_speed)
|
||||
te->speed = 1;
|
||||
te->clock_base = 1; /* Save clock base */
|
||||
memcpy(&te->tod_base, &tod_clock_base[1], 8);
|
||||
te->tod_base = tod_clock_base.tod;
|
||||
te->timestamp = get_tod_clock_fast();
|
||||
}
|
||||
|
||||
|
@ -1682,7 +1682,7 @@ static void aux_sdb_init(unsigned long sdb)
|
||||
|
||||
/* Save clock base */
|
||||
te->clock_base = 1;
|
||||
memcpy(&te->progusage2, &tod_clock_base[1], 8);
|
||||
te->progusage2 = tod_clock_base.tod;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -55,11 +55,7 @@
|
||||
#include <asm/cio.h>
|
||||
#include "entry.h"
|
||||
|
||||
unsigned char tod_clock_base[16] __aligned(8) = {
|
||||
/* Force to data section. */
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
union tod_clock tod_clock_base __section(".data");
|
||||
EXPORT_SYMBOL_GPL(tod_clock_base);
|
||||
|
||||
u64 clock_comparator_max = -1ULL;
|
||||
@ -86,7 +82,7 @@ void __init time_early_init(void)
|
||||
struct ptff_qui qui;
|
||||
|
||||
/* Initialize TOD steering parameters */
|
||||
tod_steering_end = *(unsigned long long *) &tod_clock_base[1];
|
||||
tod_steering_end = tod_clock_base.tod;
|
||||
vdso_data->arch_data.tod_steering_end = tod_steering_end;
|
||||
|
||||
if (!test_facility(28))
|
||||
@ -113,18 +109,13 @@ unsigned long long notrace sched_clock(void)
|
||||
}
|
||||
NOKPROBE_SYMBOL(sched_clock);
|
||||
|
||||
static void ext_to_timespec64(unsigned char *clk, struct timespec64 *xt)
|
||||
static void ext_to_timespec64(union tod_clock *clk, struct timespec64 *xt)
|
||||
{
|
||||
unsigned long long high, low, rem, sec, nsec;
|
||||
unsigned long rem, sec, nsec;
|
||||
|
||||
/* Split extendnd TOD clock to micro-seconds and sub-micro-seconds */
|
||||
high = (*(unsigned long long *) clk) >> 4;
|
||||
low = (*(unsigned long long *)&clk[7]) << 4;
|
||||
/* Calculate seconds and nano-seconds */
|
||||
sec = high;
|
||||
sec = clk->us;
|
||||
rem = do_div(sec, 1000000);
|
||||
nsec = (((low >> 32) + (rem << 32)) * 1000) >> 32;
|
||||
|
||||
nsec = ((clk->sus + (rem << 12)) * 125) >> 9;
|
||||
xt->tv_sec = sec;
|
||||
xt->tv_nsec = nsec;
|
||||
}
|
||||
@ -204,30 +195,26 @@ static void stp_reset(void);
|
||||
|
||||
void read_persistent_clock64(struct timespec64 *ts)
|
||||
{
|
||||
unsigned char clk[STORE_CLOCK_EXT_SIZE];
|
||||
__u64 delta;
|
||||
union tod_clock clk;
|
||||
u64 delta;
|
||||
|
||||
delta = initial_leap_seconds + TOD_UNIX_EPOCH;
|
||||
get_tod_clock_ext(clk);
|
||||
*(__u64 *) &clk[1] -= delta;
|
||||
if (*(__u64 *) &clk[1] > delta)
|
||||
clk[0]--;
|
||||
ext_to_timespec64(clk, ts);
|
||||
store_tod_clock_ext(&clk);
|
||||
clk.eitod -= delta;
|
||||
ext_to_timespec64(&clk, ts);
|
||||
}
|
||||
|
||||
void __init read_persistent_wall_and_boot_offset(struct timespec64 *wall_time,
|
||||
struct timespec64 *boot_offset)
|
||||
{
|
||||
unsigned char clk[STORE_CLOCK_EXT_SIZE];
|
||||
struct timespec64 boot_time;
|
||||
__u64 delta;
|
||||
union tod_clock clk;
|
||||
u64 delta;
|
||||
|
||||
delta = initial_leap_seconds + TOD_UNIX_EPOCH;
|
||||
memcpy(clk, tod_clock_base, STORE_CLOCK_EXT_SIZE);
|
||||
*(__u64 *)&clk[1] -= delta;
|
||||
if (*(__u64 *)&clk[1] > delta)
|
||||
clk[0]--;
|
||||
ext_to_timespec64(clk, &boot_time);
|
||||
clk = tod_clock_base;
|
||||
clk.eitod -= delta;
|
||||
ext_to_timespec64(&clk, &boot_time);
|
||||
|
||||
read_persistent_clock64(wall_time);
|
||||
*boot_offset = timespec64_sub(*wall_time, boot_time);
|
||||
@ -381,10 +368,7 @@ static void clock_sync_global(unsigned long long delta)
|
||||
struct ptff_qto qto;
|
||||
|
||||
/* Fixup the monotonic sched clock. */
|
||||
*(unsigned long long *) &tod_clock_base[1] += delta;
|
||||
if (*(unsigned long long *) &tod_clock_base[1] < delta)
|
||||
/* Epoch overflow */
|
||||
tod_clock_base[0]++;
|
||||
tod_clock_base.eitod += delta;
|
||||
/* Adjust TOD steering parameters. */
|
||||
now = get_tod_clock();
|
||||
adj = tod_steering_end - now;
|
||||
|
Loading…
Reference in New Issue
Block a user