[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] x86/ACPI: allow CMOS RTC use even when ACPI says there is none
commit e9425f05b90811458a08355a55a0b0d608c440cf Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Fri Aug 1 16:29:27 2014 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Fri Aug 1 16:29:27 2014 +0200 x86/ACPI: allow CMOS RTC use even when ACPI says there is none HP is setting the ACPI_FADT_NO_CMOS_RTC flag on newer systems, regardless of whether they're being booted from UEFI. Add a command line option to allow probing for a working RTC in that case. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- docs/misc/xen-command-line.markdown | 8 +++ xen/arch/x86/time.c | 98 ++++++++++++++++++++++++----------- 2 files changed, 76 insertions(+), 30 deletions(-) diff --git a/docs/misc/xen-command-line.markdown b/docs/misc/xen-command-line.markdown index 3ff02bd..1604c9a 100644 --- a/docs/misc/xen-command-line.markdown +++ b/docs/misc/xen-command-line.markdown @@ -218,6 +218,14 @@ If set, override Xen's calculation of the level 2 cache line size. If set, override Xen's default choice for the platform timer. +### cmos-rtc-probe +> `= <boolean>` + +> Default: `false` + +Flag to indicate whether to probe for a CMOS Real Time Clock irrespective of +ACPI indicating none to be there. + ### com1,com2 > `= > <baud>[/<clock_hz>][,[DPS][,[<io-base>|pci|amt][,[<irq>][,[<port-bdf>][,[<bridge-bdf>]]]]]]` diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index a4e1656..9e30d97 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -654,37 +654,40 @@ mktime (unsigned int year, unsigned int mon, )*60 + sec; /* finally seconds */ } -static unsigned long __get_cmos_time(void) -{ +struct rtc_time { unsigned int year, mon, day, hour, min, sec; +}; - 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); +static void __get_cmos_time(struct rtc_time *rtc) +{ + rtc->sec = CMOS_READ(RTC_SECONDS); + rtc->min = CMOS_READ(RTC_MINUTES); + rtc->hour = CMOS_READ(RTC_HOURS); + rtc->day = CMOS_READ(RTC_DAY_OF_MONTH); + rtc->mon = CMOS_READ(RTC_MONTH); + rtc->year = CMOS_READ(RTC_YEAR); if ( RTC_ALWAYS_BCD || !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) ) { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); + BCD_TO_BIN(rtc->sec); + BCD_TO_BIN(rtc->min); + BCD_TO_BIN(rtc->hour); + BCD_TO_BIN(rtc->day); + BCD_TO_BIN(rtc->mon); + BCD_TO_BIN(rtc->year); } - if ( (year += 1900) < 1970 ) - year += 100; - - return mktime(year, mon, day, hour, min, sec); + if ( (rtc->year += 1900) < 1970 ) + rtc->year += 100; } static unsigned long get_cmos_time(void) { unsigned long res, flags; - int i; + struct rtc_time rtc; + unsigned int seconds = 60; + static bool_t __read_mostly cmos_rtc_probe; + boolean_param("cmos-rtc-probe", cmos_rtc_probe); if ( efi_enabled ) { @@ -693,23 +696,58 @@ static unsigned long get_cmos_time(void) return res; } - if ( unlikely(acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC) ) - panic("System without CMOS RTC must be booted from EFI"); + if ( likely(!(acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC)) ) + cmos_rtc_probe = 0; + else if ( system_state < SYS_STATE_smp_boot && !cmos_rtc_probe ) + panic("System with no CMOS RTC advertised must be booted from EFI" + " (or with command line option \"cmos-rtc-probe\")"); + + for ( ; ; ) + { + s_time_t start, t1, t2; + + spin_lock_irqsave(&rtc_lock, flags); + + /* read RTC exactly on falling edge of update flag */ + start = NOW(); + do { /* may take up to 1 second... */ + t1 = NOW() - start; + } while ( !(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) && + t1 <= SECONDS(1) ); - spin_lock_irqsave(&rtc_lock, flags); + start = NOW(); + do { /* must try at least 2.228 ms */ + t2 = NOW() - start; + } while ( (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) && + t2 < MILLISECS(3) ); - /* 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) ) + __get_cmos_time(&rtc); + + spin_unlock_irqrestore(&rtc_lock, flags); + + if ( likely(!cmos_rtc_probe) || + t1 > SECONDS(1) || t2 >= MILLISECS(3) || + rtc.sec >= 60 || rtc.min >= 60 || rtc.hour >= 24 || + !rtc.day || rtc.day > 31 || + !rtc.mon || rtc.mon > 12 ) break; - for ( i = 0 ; i < 1000000 ; i++ ) /* must try at least 2.228 ms */ - if ( !(CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) ) + + if ( seconds < 60 ) + { + if ( rtc.sec != seconds ) + cmos_rtc_probe = 0; break; + } + + process_pending_softirqs(); + + seconds = rtc.sec; + } - res = __get_cmos_time(); + if ( unlikely(cmos_rtc_probe) ) + panic("No CMOS RTC found - system must be booted from EFI"); - spin_unlock_irqrestore(&rtc_lock, flags); - return res; + return mktime(rtc.year, rtc.mon, rtc.day, rtc.hour, rtc.min, rtc.sec); } /*************************************************************************** -- generated by git-patchbot for /home/xen/git/xen.git#master _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |