Index: 2006-01-05/arch/i386/kernel/time-xen.c =================================================================== --- 2006-01-05.orig/arch/i386/kernel/time-xen.c 2006-01-09 15:34:26.000000000 +0100 +++ 2006-01-05/arch/i386/kernel/time-xen.c 2006-01-10 11:39:01.148336280 +0100 @@ -60,11 +60,14 @@ #ifdef __i386__ #include #else -#define TICK_SIZE (tick_nsec / 1000) #include #endif +#ifdef __i386__ #include "mach_time.h" +#else +#include +#endif #include #include @@ -319,6 +322,7 @@ static inline int time_values_up_to_date return (dst->version == src->version); } +#ifdef __i386__ /* * This is a special lock that is owned by the CPU and holds the index * register we are working with. It is required for NMI access to the @@ -347,6 +351,7 @@ void rtc_cmos_write(unsigned char val, u lock_cmos_suffix(addr); } EXPORT_SYMBOL(rtc_cmos_write); +#endif /* * This version of gettimeofday has microsecond resolution @@ -477,9 +482,10 @@ int do_settimeofday(struct timespec *tv) EXPORT_SYMBOL(do_settimeofday); -#ifdef CONFIG_XEN_PRIVILEGED_GUEST +#ifdef __i386__ static int set_rtc_mmss(unsigned long nowtime) { +#ifdef CONFIG_XEN_PRIVILEGED_GUEST int retval; WARN_ON(irqs_disabled()); @@ -496,11 +502,9 @@ static int set_rtc_mmss(unsigned long no spin_unlock_irq(&rtc_lock); return retval; -} #else -static int set_rtc_mmss(unsigned long nowtime) -{ return 0; +#endif } #endif @@ -631,9 +635,9 @@ irqreturn_t timer_interrupt(int irq, voi return IRQ_HANDLED; } -/* not static: needed by APM */ -unsigned long get_cmos_time(void) +static unsigned long get_cmos_time(void) { +#ifdef __i386__ unsigned long retval; spin_lock(&rtc_lock); @@ -646,9 +650,64 @@ unsigned long get_cmos_time(void) spin_unlock(&rtc_lock); return retval; +#else + unsigned int timeout = 1000000, year, mon, day, hour, min, sec; + unsigned char uip = 0, this = 0; + unsigned long flags; + +/* + * The Linux interpretation of the CMOS clock register contents: When the + * Update-In-Progress (UIP) flag goes from 1 to 0, the RTC registers show the + * second which has precisely just started. Waiting for this can take up to 1 + * second, we timeout approximately after 2.4 seconds on a machine with + * standard 8.3 MHz ISA bus. + */ + + spin_lock_irqsave(&rtc_lock, flags); + + while (timeout && (!uip || this)) { + uip |= this; + this = CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP; + timeout--; + } + +/* + * Here we are safe to assume the registers won't change for a whole second, so + * we just go ahead and read them. + */ + + sec = CMOS_READ(RTC_SECONDS); + min = CMOS_READ(RTC_MINUTES); + hour = CMOS_READ(RTC_HOURS); + day = CMOS_READ(RTC_DAY_OF_MONTH); + mon = CMOS_READ(RTC_MONTH); + year = CMOS_READ(RTC_YEAR); + + spin_unlock_irqrestore(&rtc_lock, flags); + +/* + * We know that x86-64 always uses BCD format, no need to check the config + * register. + */ + + BCD_TO_BIN(sec); + BCD_TO_BIN(min); + BCD_TO_BIN(hour); + BCD_TO_BIN(day); + BCD_TO_BIN(mon); + BCD_TO_BIN(year); + +/* + * x86-64 systems only exists since 2002. + * This will work up to Dec 31, 2100 + */ + year += 2000; + + return mktime(year, mon, day, hour, min, sec); +#endif } -EXPORT_SYMBOL(get_cmos_time); +#ifdef __i386__ static void sync_cmos_clock(unsigned long dummy); static DEFINE_TIMER(sync_cmos_timer, sync_cmos_clock, 0, 0); @@ -697,6 +756,7 @@ void notify_arch_cmos_timer(void) { mod_timer(&sync_cmos_timer, jiffies + 1); } +#endif static long clock_cmos_diff, sleep_start; Index: 2006-01-05/arch/x86_64/kernel/x8664_ksyms-xen.c =================================================================== --- 2006-01-05.orig/arch/x86_64/kernel/x8664_ksyms-xen.c 2006-01-05 16:43:44.000000000 +0100 +++ 2006-01-05/arch/x86_64/kernel/x8664_ksyms-xen.c 2006-01-10 09:17:27.332592544 +0100 @@ -40,8 +40,6 @@ extern void __write_lock_failed(rwlock_t extern void __read_lock_failed(rwlock_t *rw); #endif -extern unsigned long get_cmos_time(void); - /* platform dependent support */ EXPORT_SYMBOL(boot_cpu_data); //EXPORT_SYMBOL(dump_fpu); @@ -57,7 +55,6 @@ EXPORT_SYMBOL(pm_idle); #ifdef CONFIG_ACPI EXPORT_SYMBOL(pm_power_off); #endif -EXPORT_SYMBOL(get_cmos_time); EXPORT_SYMBOL(__down_failed); EXPORT_SYMBOL(__down_failed_interruptible); Index: 2006-01-05/include/asm-x86_64/mach-xen/mach_time.h =================================================================== --- 2006-01-05.orig/include/asm-x86_64/mach-xen/mach_time.h 2005-11-21 16:42:15.000000000 +0100 +++ /dev/null 1970-01-01 00:00:00.000000000 +0000 @@ -1,122 +0,0 @@ -/* - * include/asm-i386/mach-default/mach_time.h - * - * Machine specific set RTC function for generic. - * Split out from time.c by Osamu Tomita - */ -#ifndef _MACH_TIME_H -#define _MACH_TIME_H - -#include - -/* for check timing call set_rtc_mmss() 500ms */ -/* used in arch/i386/time.c::do_timer_interrupt() */ -#define USEC_AFTER 500000 -#define USEC_BEFORE 500000 - -/* - * In order to set the CMOS clock precisely, set_rtc_mmss has to be - * called 500 ms after the second nowtime has started, because when - * nowtime is written into the registers of the CMOS clock, it will - * jump to the next second precisely 500 ms later. Check the Motorola - * MC146818A or Dallas DS12887 data sheet for details. - * - * BUG: This routine does not handle hour overflow properly; it just - * sets the minutes. Usually you'll only notice that after reboot! - */ -static inline int mach_set_rtc_mmss(unsigned long nowtime) -{ - int retval = 0; - int real_seconds, real_minutes, cmos_minutes; - unsigned char save_control, save_freq_select; - - save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); - - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); - - cmos_minutes = CMOS_READ(RTC_MINUTES); - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - BCD_TO_BIN(cmos_minutes); - - /* - * since we're only adjusting minutes and seconds, - * don't interfere with hour overflow. This avoids - * messing with unknown time zones but requires your - * RTC not to be off by more than 15 minutes - */ - real_seconds = nowtime % 60; - real_minutes = nowtime / 60; - if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1) - real_minutes += 30; /* correct for half hour time zone */ - real_minutes %= 60; - - if (abs(real_minutes - cmos_minutes) < 30) { - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(real_seconds); - BIN_TO_BCD(real_minutes); - } - CMOS_WRITE(real_seconds,RTC_SECONDS); - CMOS_WRITE(real_minutes,RTC_MINUTES); - } else { - printk(KERN_WARNING - "set_rtc_mmss: can't update from %d to %d\n", - cmos_minutes, real_minutes); - retval = -1; - } - - /* The following flags have to be released exactly in this order, - * otherwise the DS12887 (popular MC146818A clone with integrated - * battery and quartz) will not reset the oscillator and will not - * update precisely 500 ms later. You won't find this mentioned in - * the Dallas Semiconductor data sheets, but who believes data - * sheets anyway ... -- Markus Kuhn - */ - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - - return retval; -} - -static inline unsigned long mach_get_cmos_time(void) -{ - unsigned int year, mon, day, hour, min, sec; - int i; - - /* The Linux interpretation of the CMOS clock register contents: - * When the Update-In-Progress (UIP) flag goes from 1 to 0, the - * RTC registers show the second which has precisely just started. - * Let's hope other operating systems interpret the RTC the same way. - */ - /* read RTC exactly on falling edge of update flag */ - for (i = 0 ; i < 1000000 ; i++) /* may take up to 1 second... */ - if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) - break; - for (i = 0 ; i < 1000000 ; i++) /* must try at least 2.228 ms */ - if (!(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP)) - break; - do { /* Isn't this overkill ? UIP above should guarantee consistency */ - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - } while (sec != CMOS_READ(RTC_SECONDS)); - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) - { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - } - if ((year += 1900) < 1970) - year += 100; - - return mktime(year, mon, day, hour, min, sec); -} - -#endif /* !_MACH_TIME_H */