|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen master] x86/time: CMOS RTC may run in binary mode
commit 9d2bbfb79789e9bdfc7239ffca195d102c287559
Author: Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Wed Sep 2 15:11:50 2026 +0200
Commit: Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Wed Sep 2 15:11:50 2026 +0200
x86/time: CMOS RTC may run in binary mode
Indicating it would always use BCD mode is just wrong (and then the
comment there said the opposite). All halfway recent (and really all 64-
bit capable) systems having a CMOS RTC should properly indicate the mode
in control register B.
Make use of the flag, but provide a fallback mechanism in case people run
into systems not matching the above assumption. Additionally, when binary
mode is indicated and when "cmos-rtc-probe" is in use (but "cmos-rtc-bcd"
isn't), probe whether the clock really runs in binary mode. (This probing,
sadly, can take up to 10 seconds.)
Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
Acked-by: Roger Pau Monné <roger@xxxxxxxxxxxxxx>
---
docs/misc/xen-command-line.pandoc | 8 ++++++
xen/arch/x86/include/asm/mc146818rtc.h | 1 -
xen/arch/x86/time.c | 51 +++++++++++++++++++++++++++++++++-
3 files changed, 58 insertions(+), 2 deletions(-)
diff --git a/docs/misc/xen-command-line.pandoc
b/docs/misc/xen-command-line.pandoc
index 1c711fa980..95cc3312f1 100644
--- a/docs/misc/xen-command-line.pandoc
+++ b/docs/misc/xen-command-line.pandoc
@@ -339,6 +339,14 @@ parameter to "stable:socket".
Specify the event count threshold for raising Corrected Machine Check
Interrupts. Specifying zero disables CMCI handling.
+### cmos-rtc-bcd (x86)
+> `= <boolean>`
+
+> Default: `false`
+
+Flag to indicate the CMOS Real Time Clock uses BCD mode irrespective of
+control register B indicating binary mode.
+
### cmos-rtc-probe (x86)
> `= <boolean>`
diff --git a/xen/arch/x86/include/asm/mc146818rtc.h
b/xen/arch/x86/include/asm/mc146818rtc.h
index 1a34512d29..2c02caba4d 100644
--- a/xen/arch/x86/include/asm/mc146818rtc.h
+++ b/xen/arch/x86/include/asm/mc146818rtc.h
@@ -96,7 +96,6 @@ bool is_cmos_port(unsigned int port, unsigned int bytes,
#ifndef RTC_PORT
#define RTC_PORT(x) (0x70 + (x))
-#define RTC_ALWAYS_BCD 1 /* RTC operates in binary mode */
#endif
/*
diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c
index bc0161f7c2..f35555f185 100644
--- a/xen/arch/x86/time.c
+++ b/xen/arch/x86/time.c
@@ -1250,6 +1250,9 @@ mktime (unsigned int year, unsigned int mon,
)*60 + sec; /* finally seconds */
}
+static bool __ro_after_init opt_cmos_rtc_bcd;
+boolean_param("cmos-rtc-bcd", opt_cmos_rtc_bcd);
+
struct rtc_time {
unsigned int year, mon, day, hour, min, sec;
};
@@ -1285,7 +1288,7 @@ static bool __get_cmos_time(struct rtc_time *rtc)
if ( acpi_gbl_FADT.century && acpi_gbl_FADT.century < 0x80 )
century = CMOS_READ(acpi_gbl_FADT.century);
- bcd = RTC_ALWAYS_BCD || !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY);
+ bcd = opt_cmos_rtc_bcd || !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY);
spin_unlock_irqrestore(&rtc_lock, flags);
@@ -1353,6 +1356,48 @@ static bool __init cmos_rtc_probe(void)
return false;
}
+static inline bool __init attr_const is_bcd(unsigned int x)
+{
+ return (x & 0xf) < 10 && (x >> 4) < 10;
+}
+
+static void __init cmos_rtc_probe_bcd(void)
+{
+ bool bcd;
+ unsigned long flags;
+
+ if ( opt_cmos_rtc_bcd )
+ return;
+
+ spin_lock_irqsave(&rtc_lock, flags);
+ bcd = !(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY);
+ spin_unlock_irqrestore(&rtc_lock, flags);
+
+ if ( bcd )
+ return;
+
+ for ( unsigned int seclo = 0; ; )
+ {
+ struct rtc_time rtc;
+
+ if ( !__get_cmos_time(&rtc) ||
+ !is_bcd(rtc.sec) ||
+ !is_bcd(rtc.min) ||
+ !is_bcd(rtc.hour) ||
+ !is_bcd(rtc.day) ||
+ !is_bcd(rtc.mon) )
+ return;
+
+ if ( seclo > (rtc.sec & 0xf) )
+ break;
+
+ seclo = rtc.sec & 0xf;
+ }
+
+ printk(XENLOG_WARNING "CMOS RTC indicates binary mode but uses BCD\n");
+
+ opt_cmos_rtc_bcd = true;
+}
static unsigned long cmos_rtc_read(void)
{
@@ -1614,6 +1659,10 @@ static void __init probe_wallclock(void)
if ( cmos_rtc_probe() )
{
wallclock_source = WALLCLOCK_CMOS;
+
+ if ( opt_cmos_rtc_probe )
+ cmos_rtc_probe_bcd();
+
return;
}
if ( efi_enabled(EFI_RS) && efi_get_time() )
--
generated by git-patchbot for /home/xen/git/xen.git#master
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |