Messages in this thread | | | Subject | Re: [PATCH v2] Added "Preserve Boot Time Support" | From | Oleksij Rempel <> | Date | Thu, 4 May 2017 11:27:22 +0200 |
| |
Hi Bogdan,
are there any example what and how bootloader should do to provide correct values?
On 05/03/2017 12:59 PM, Bogdan Mirea wrote: > This option enables Boot Time Preservation between Bootloader and > Linux Kernel. It is based on the idea that the Bootloader (or any > other early firmware) will start the HW Timer and Linux Kernel will > count the time starting with the cycles elapsed since timer start. > > The sched_clock part is preserving boottime for kmsg which should be in > sync with system uptime. The system uptime part is driver specific and I > updated the arm_arch_timer with an arch_timer_setsystime() function > which will call do_settimeofday64() with the values read from arch timer > counter. > > This way both kmsg and uptime will be in sync, otherwise incosistencies > will appear between the two. > > Signed-off-by: Bogdan Mirea <Bogdan-Stefan_mirea@mentor.com> > --- > drivers/clocksource/arm_arch_timer.c | 26 ++++++++++++++++++++++++++ > kernel/time/Kconfig | 8 ++++++++ > kernel/time/sched_clock.c | 6 ++++++ > 3 files changed, 40 insertions(+) > > diff --git a/drivers/clocksource/arm_arch_timer.c b/drivers/clocksource/arm_arch_timer.c > index 5152b38..7f9bf2a 100644 > --- a/drivers/clocksource/arm_arch_timer.c > +++ b/drivers/clocksource/arm_arch_timer.c > @@ -475,6 +475,28 @@ struct timecounter *arch_timer_get_timecounter(void) > return &timecounter; > } > > +#ifdef CONFIG_BOOT_TIME_PRESERVE > +/* > + * Set the real system time(including the time spent in bootloader) > + * based on the timer counter. > + */ > +void arch_timer_setsystime(void) > +{ > + static struct timespec64 boot_ts; > + static cycles_t cycles; > + unsigned long long nsecs; > + > + cycles = arch_timer_read_counter() ? arch_timer_read_counter() : 0; > + > + nsecs = clocksource_cyc2ns(cycles, clocksource_counter.mult, > + clocksource_counter.shift); > + timespec64_add_ns(&boot_ts, nsecs); > + > + if (do_settimeofday64(&boot_ts)) > + pr_warn("arch_timer: unable to set systime\n"); > +} > +#endif /* CONFIG_BOOT_TIME_PRESERVE */ > + > static void __init arch_counter_register(unsigned type) > { > u64 start_count; > @@ -504,6 +526,10 @@ static void __init arch_counter_register(unsigned type) > > /* 56 bits minimum, so we assume worst case rollover */ > sched_clock_register(arch_timer_read_counter, 56, arch_timer_rate); > +#ifdef CONFIG_BOOT_TIME_PRESERVE > + /* Set systime */ > + arch_timer_setsystime(); > +#endif /* CONFIG_BOOT_TIME_PRESERVE */ > } > > static void arch_timer_stop(struct clock_event_device *clk) > diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig > index 4008d9f..7d70232 100644 > --- a/kernel/time/Kconfig > +++ b/kernel/time/Kconfig > @@ -193,5 +193,13 @@ config HIGH_RES_TIMERS > hardware is not capable then this option only increases > the size of the kernel image. > > +config BOOT_TIME_PRESERVE > + bool "Preserve Boot Time Support" > + help > + This option enables Boot Time Preservation between Bootloader and > + Linux Kernel. It is based on the idea that the Bootloader (or any > + other early firmware) will start the HW Timer and Linux Kernel will > + count the time starting with the cycles elapsed since timer start. > + > endmenu > endif > diff --git a/kernel/time/sched_clock.c b/kernel/time/sched_clock.c > index a26036d..1d6e35a 100644 > --- a/kernel/time/sched_clock.c > +++ b/kernel/time/sched_clock.c > @@ -193,7 +193,13 @@ sched_clock_register(u64 (*read)(void), int bits, unsigned long rate) > /* Update epoch for new counter and update 'epoch_ns' from old counter*/ > new_epoch = read(); > cyc = cd.actual_read_sched_clock(); > + > +#ifdef CONFIG_BOOT_TIME_PRESERVE > + ns = rd.epoch_ns + cyc_to_ns((new_epoch - rd.epoch_cyc) & new_mask, new_mult, new_shift); > +#else > ns = rd.epoch_ns + cyc_to_ns((cyc - rd.epoch_cyc) & rd.sched_clock_mask, rd.mult, rd.shift); > +#endif /* CONFIG_BOOT_TIME_PRESERVE */ > + > cd.actual_read_sched_clock = read; > > rd.read_sched_clock = read; >
| |