|
[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 |