From: Kees Jongenburger Date: Fri, 27 Sep 2013 09:29:04 +0000 (+0200) Subject: arm:ensure read_tsc_64 always returns a valid value. X-Git-Tag: v3.3.0~769 X-Git-Url: http://zhaoyanbai.com/repos/Bv9ARM.ch06.html?a=commitdiff_plain;h=ed45d98dac23186a4a1f8085458dc55369e40a6a;p=minix.git arm:ensure read_tsc_64 always returns a valid value. Before this change overflowing the free running clock counter between the time the timer was read and the time the overflow check was done resulted in read_tsc_64 returning a to high value. Change-Id: I1022f271213647f720477c4121d45f0c965456c6 --- diff --git a/kernel/arch/earm/omap_timer.c b/kernel/arch/earm/omap_timer.c index 065674132..cb2c2a1ec 100644 --- a/kernel/arch/earm/omap_timer.c +++ b/kernel/arch/earm/omap_timer.c @@ -269,11 +269,24 @@ static u32_t read_frc(void) return mmio_read(fr_timer.base + fr_timer.regs->TCRR); } -static void frc_overflow_check(void) +/* + * Check if the free running clock has overflown and + * increase the high free running clock counter if + * so. This method takes the current timer value as + * parameter to ensure the overflow check is done + * on the current timer value. + * + * To compose the current timer value (64 bits) you + * need to follow the following sequence: + * read the current timer value. + * call the overflow check + * compose the 64 bits time based on the current timer value + * and high_frc. + */ +static void frc_overflow_check(u32_t cur_frc) { static int prev_frc_valid; static u32_t prev_frc; - u32_t cur_frc = read_frc(); if(prev_frc_valid && prev_frc > cur_frc) high_frc++; prev_frc = cur_frc; @@ -283,7 +296,7 @@ static void frc_overflow_check(void) void omap3_timer_int_handler() { /* Clear all interrupts */ - u32_t tisr; + u32_t tisr,now; /* when the kernel itself is running interrupts are disabled. @@ -294,14 +307,15 @@ void omap3_timer_int_handler() OMAP3_TISR_TCAR_IT_FLAG; mmio_write(timer.base + timer.regs->TISR, tisr); - frc_overflow_check(); + now = read_frc(); + frc_overflow_check(now); } /* Use the free running clock as TSC */ void read_tsc_64(u64_t *t) { u32_t now; - frc_overflow_check(); now = read_frc(); + frc_overflow_check(now); *t = (u64_t) now + (high_frc << 32); }