Remove struct timer_opts left-overs, add a Xen clocksource, and adjust conditionals for x86-64. Signed-off-by: Jan Beulich <jbeulich@novell.com> Index: head-2007-02-27/arch/i386/Kconfig ==================================================================--- head-2007-02-27.orig/arch/i386/Kconfig 2007-03-05 10:00:18.000000000 +0100 +++ head-2007-02-27/arch/i386/Kconfig 2007-02-27 16:27:37.000000000 +0100 @@ -16,7 +16,6 @@ config X86_32 config GENERIC_TIME bool - depends on !X86_XEN default y config LOCKDEP_SUPPORT Index: head-2007-02-27/arch/i386/kernel/Makefile ==================================================================--- head-2007-02-27.orig/arch/i386/kernel/Makefile 2007-03-05 10:00:18.000000000 +0100 +++ head-2007-02-27/arch/i386/kernel/Makefile 2007-02-27 16:27:37.000000000 +0100 @@ -93,7 +93,7 @@ include $(srctree)/scripts/Makefile.xen obj-y += fixup.o microcode-$(subst m,y,$(CONFIG_MICROCODE)) := microcode-xen.o -n-obj-xen := i8259.o timers/ reboot.o smpboot.o trampoline.o +n-obj-xen := i8259.o reboot.o smpboot.o trampoline.o tsc.o obj-y := $(call filterxen, $(obj-y), $(n-obj-xen)) obj-y := $(call cherrypickxen, $(obj-y)) Index: head-2007-02-27/arch/i386/kernel/time-xen.c ==================================================================--- head-2007-02-27.orig/arch/i386/kernel/time-xen.c 2007-03-05 10:00:18.000000000 +0100 +++ head-2007-02-27/arch/i386/kernel/time-xen.c 2007-02-27 16:27:37.000000000 +0100 @@ -96,10 +96,6 @@ extern unsigned long wall_jiffies; DEFINE_SPINLOCK(rtc_lock); EXPORT_SYMBOL(rtc_lock); -extern struct init_timer_opts timer_tsc_init; -extern struct timer_opts timer_tsc; -#define timer_none timer_tsc - /* These are peridically updated in shared_info, and then copied here. */ struct shadow_time_info { u64 tsc_timestamp; /* TSC at last update of time vals. */ @@ -238,6 +234,7 @@ static u64 get_nsec_offset(struct shadow return scale_delta(delta, shadow->tsc_to_nsec_mul, shadow->tsc_shift); } +#ifdef CONFIG_X86_64 static unsigned long get_usec_offset(struct shadow_time_info *shadow) { u64 now, delta; @@ -245,6 +242,7 @@ static unsigned long get_usec_offset(str delta = now - shadow->tsc_timestamp; return scale_delta(delta, shadow->tsc_to_usec_mul, shadow->tsc_shift); } +#endif static void __update_wallclock(time_t sec, long nsec) { @@ -354,6 +352,8 @@ void rtc_cmos_write(unsigned char val, u } EXPORT_SYMBOL(rtc_cmos_write); +#ifdef CONFIG_X86_64 + /* * This version of gettimeofday has microsecond resolution * and better than microsecond precision on fast x86 machines with TSC. @@ -482,6 +482,8 @@ int do_settimeofday(struct timespec *tv) EXPORT_SYMBOL(do_settimeofday); +#endif + static void sync_xen_wallclock(unsigned long dummy); static DEFINE_TIMER(sync_xen_wallclock_timer, sync_xen_wallclock, 0, 0); static void sync_xen_wallclock(unsigned long dummy) @@ -533,11 +535,15 @@ static int set_rtc_mmss(unsigned long no return retval; } +#ifdef CONFIG_X86_64 /* monotonic_clock(): returns # of nanoseconds passed since time_init() * Note: This function is required to return accurate * time even in the absence of multiple timer ticks. */ unsigned long long monotonic_clock(void) +#else +unsigned long long sched_clock(void) +#endif { int cpu = get_cpu(); struct shadow_time_info *shadow = &per_cpu(shadow_time, cpu); @@ -557,9 +563,9 @@ unsigned long long monotonic_clock(void) return time; } +#ifdef CONFIG_X86_64 EXPORT_SYMBOL(monotonic_clock); -#ifdef __x86_64__ unsigned long long sched_clock(void) { return monotonic_clock(); @@ -927,11 +933,11 @@ void __init time_init(void) update_wallclock(); +#ifdef CONFIG_X86_64 init_cpu_khz(); printk(KERN_INFO "Xen reported: %u.%03u MHz processor.\n", cpu_khz / 1000, cpu_khz % 1000); -#if defined(__x86_64__) vxtime.mode = VXTIME_TSC; vxtime.quot = (1000000L << 32) / vxtime_hz; vxtime.tsc_quot = (1000L << 32) / cpu_khz; @@ -1074,6 +1080,58 @@ void local_teardown_timer(unsigned int c } #endif +#ifndef CONFIG_X86_64 + +void tsc_init(void) +{ + init_cpu_khz(); + printk(KERN_INFO "Xen reported: %u.%03u MHz processor.\n", + cpu_khz / 1000, cpu_khz % 1000); + + use_tsc_delay(); +} + +#include <linux/clocksource.h> + +void mark_tsc_unstable(void) +{ +#ifndef CONFIG_XEN /* XXX Should tell the hypervisor about this fact. */ + tsc_unstable = 1; +#endif +} +EXPORT_SYMBOL_GPL(mark_tsc_unstable); + +static cycle_t read_tsc(void) +{ + cycle_t ret; + + rdtscll(ret); + + return ret; +} + +static struct clocksource clocksource_xen = { + .name = "xen", + .rating = 300, + .read = read_tsc, + .mask = CLOCKSOURCE_MASK(64), + .mult = 0, /* to be set */ + .shift = 22, + .is_continuous = 1, +}; + +static int __init init_xen_clocksource(void) +{ + clocksource_xen.mult = clocksource_khz2mult(cpu_khz, + clocksource_xen.shift); + + return clocksource_register(&clocksource_xen); +} + +module_init(init_xen_clocksource); + +#endif + /* * /proc/sys/xen: This really belongs in another file. It can stay here for * now however. Index: head-2007-02-27/include/asm-i386/mach-xen/asm/processor.h ==================================================================--- head-2007-02-27.orig/include/asm-i386/mach-xen/asm/processor.h 2007-03-05 10:00:18.000000000 +0100 +++ head-2007-02-27/include/asm-i386/mach-xen/asm/processor.h 2007-02-27 16:27:37.000000000 +0100 @@ -23,7 +23,7 @@ #include <xen/interface/physdev.h> /* flag for disabling the tsc */ -extern int tsc_disable; +#define tsc_disable 0 struct desc_struct { unsigned long a,b; Index: head-2007-02-27/include/asm-x86_64/mach-xen/asm/timer.h ==================================================================--- head-2007-02-27.orig/include/asm-x86_64/mach-xen/asm/timer.h 2007-03-05 11:14:12.000000000 +0100 +++ head-2007-02-27/include/asm-x86_64/mach-xen/asm/timer.h 2007-03-05 11:14:28.000000000 +0100 @@ -2,39 +2,8 @@ #define _ASMi386_TIMER_H #include <linux/init.h> -/** - * struct timer_ops - used to define a timer source - * - * @name: name of the timer. - * @init: Probes and initializes the timer. Takes clock= override - * string as an argument. Returns 0 on success, anything else - * on failure. - * @mark_offset: called by the timer interrupt. - * @get_offset: called by gettimeofday(). Returns the number of microseconds - * since the last timer interupt. - * @monotonic_clock: returns the number of nanoseconds since the init of the - * timer. - * @delay: delays this many clock cycles. - */ -struct timer_opts { - char* name; - void (*mark_offset)(void); - unsigned long (*get_offset)(void); - unsigned long long (*monotonic_clock)(void); - void (*delay)(unsigned long); - unsigned long (*read_timer)(void); - int (*suspend)(pm_message_t state); - int (*resume)(void); -}; - -struct init_timer_opts { - int (*init)(char *override); - struct timer_opts *opts; -}; - #define TICK_SIZE (tick_nsec / 1000) -extern struct timer_opts* __init select_timer(void); extern void clock_fallback(void); void setup_pit_timer(void); @@ -42,26 +11,13 @@ void setup_pit_timer(void); extern int pit_latch_buggy; -extern struct timer_opts *cur_timer; extern int timer_ack; /* list of externed timers */ -extern struct timer_opts timer_none; -extern struct timer_opts timer_pit; -extern struct init_timer_opts timer_pit_init; -extern struct init_timer_opts timer_tsc_init; -#ifdef CONFIG_X86_CYCLONE_TIMER -extern struct init_timer_opts timer_cyclone_init; -#endif - extern unsigned long calibrate_tsc(void); extern void init_cpu_khz(void); #ifdef CONFIG_HPET_TIMER -extern struct init_timer_opts timer_hpet_init; extern unsigned long calibrate_tsc_hpet(unsigned long *tsc_hpet_quotient_ptr); #endif -#ifdef CONFIG_X86_PM_TIMER -extern struct init_timer_opts timer_pmtmr_init; -#endif #endif _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Keir Fraser
2007-Mar-05 15:03 UTC
Re: [Xen-devel] [PATCH 7/10] linux 2.6.18: time handling
On 5/3/07 11:17, "Jan Beulich" <jbeulich@novell.com> wrote:> Remove struct timer_opts left-overs, add a Xen clocksource, and adjust > conditionals for x86-64. > > Signed-off-by: Jan Beulich <jbeulich@novell.com>There doesn''t seem to be much advantage to this (we''re already very diverged from native i386 time handling) and the disadvantages are a bigger diff versus what we need for x86/64 (hence more ifdefs) and independent_wallclock probably stops working. This is all solvable I''m sure, particularly if clocksources are the way of the future (e.g., is x86/64 native going to use generic_time any time soon)? -- Keir _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jan Beulich
2007-Mar-05 15:09 UTC
Re: [Xen-devel] [PATCH 7/10] linux 2.6.18: time handling
>... and independent_wallclock probably stops working.We didn''t notice any malfunction in time handling so far (which included the released SuSE 10.2) - how would you expect such a problem to surface? Jan _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Keir Fraser
2007-Mar-05 15:20 UTC
Re: [Xen-devel] [PATCH 7/10] linux 2.6.18: time handling
On 5/3/07 15:09, "Jan Beulich" <jbeulich@novell.com> wrote:>> ... and independent_wallclock probably stops working. > > We didn''t notice any malfunction in time handling so far (which included the > released SuSE 10.2) - how would you expect such a problem to surface?For example, settimeofday() will not be ignored for ordinary domUs. Also settimeofday() calls in dom0 will not immediately propagate their effect to other domains (but should happen during the once-per-minute wallclock propagation to Xen). Small-ish but potentially annoying issues. -- Keir _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Keir Fraser
2007-Mar-06 11:38 UTC
Re: [Xen-devel] [PATCH 7/10] linux 2.6.18: time handling
On 5/3/07 11:17, "Jan Beulich" <jbeulich@novell.com> wrote:> Remove struct timer_opts left-overs, add a Xen clocksource, and adjust > conditionals for x86-64. > > Signed-off-by: Jan Beulich <jbeulich@novell.com>The other issue afaics is that the clocksource simply does raw reads of the TSC, subsequently scaled by cpu_khz. This isn''t very accurate and will cause horrible problems if some CPUs enter power-saving modes (not explicitly supported yet, but can happen due to auto thermal throttling) or on bigger systems where TSCs may not be driven from the same mainboard clock (and hence will drift). I think Jeremy Fitzhardinge has an alternative clocksource patch which iirc is more in line with how Xen time works (should advertise a GHz frequency clocksource, and do scaling of the TSC value according to time-record values read from shared_info). Having thought about this some more I think clocksource support is worth getting into our tree, but let''s look at both available patches and decide which is the better basis for further work. Jeremy: If I''m not mistaken and you do have a patch floating around, could you post it? Thanks, Keir _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel
Jeremy Fitzhardinge
2007-Mar-06 15:50 UTC
Re: [Xen-devel] [PATCH 7/10] linux 2.6.18: time handling
Keir Fraser wrote:> I think Jeremy Fitzhardinge has an alternative clocksource patch which iirc > is more in line with how Xen time works (should advertise a GHz frequency > clocksource, and do scaling of the TSC value according to time-record values > read from shared_info). Having thought about this some more I think > clocksource support is worth getting into our tree, but let''s look at both > available patches and decide which is the better basis for further work. > > Jeremy: If I''m not mistaken and you do have a patch floating around, could > you post it? >Yes, there''s a Xen clocksource in the pv_ops tree. There''s no nicely separable patch, but the mechanism is pretty simple. I''ve attached arch/i386/xen/time.c J _______________________________________________ Xen-devel mailing list Xen-devel@lists.xensource.com http://lists.xensource.com/xen-devel