powerpc: Remove broken GregorianDay()
authorDaniel Axtens <dja@axtens.net>
Tue, 15 Dec 2015 07:09:14 +0000 (18:09 +1100)
committerMichael Ellerman <mpe@ellerman.id.au>
Wed, 16 Dec 2015 01:54:04 +0000 (12:54 +1100)
GregorianDay() is supposed to calculate the day of the week
(tm->tm_wday) for a given day/month/year. In that calcuation it
indexed into an array called MonthOffset using tm->tm_mon-1. However
tm_mon is zero-based, not one-based, so this is off-by-one. It also
means that every January, GregoiranDay() will access element -1 of
the MonthOffset array.

It also doesn't appear to be a correct algorithm either: see in
contrast kernel/time/timeconv.c's time_to_tm function.

It's been broken forever, which suggests no-one in userland uses
this. It looks like no-one in the kernel uses tm->tm_wday either
(see e.g. drivers/rtc/rtc-ds1305.c:319).

tm->tm_wday is conventionally set to -1 when not available in
hardware so we can simply set it to -1 and drop the function.
(There are over a dozen other drivers in drivers/rtc that do
this.)

Found using UBSAN.

Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Andrew Morton <akpm@linux-foundation.org> # as an example of what UBSan finds.
Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Cc: rtc-linux@googlegroups.com
Signed-off-by: Daniel Axtens <dja@axtens.net>
Acked-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/include/asm/time.h
arch/powerpc/kernel/time.c
arch/powerpc/platforms/maple/time.c
arch/powerpc/platforms/powernv/opal-rtc.c
drivers/rtc/rtc-opal.c

index 10fc784a2ad4cbf687ce28b1d2bc2d6c06fed5b4..2d7109a8d2961f440193e47ecc2602a5729e018e 100644 (file)
@@ -27,7 +27,6 @@ extern struct clock_event_device decrementer_clockevent;
 
 struct rtc_time;
 extern void to_tm(int tim, struct rtc_time * tm);
-extern void GregorianDay(struct rtc_time *tm);
 extern void tick_broadcast_ipi_handler(void);
 
 extern void generic_calibrate_decr(void);
index 1be1092c72042b9d4fbf91d601ded3f23669c730..81b0900a39eef095a917a4471f4b09753c988ede 100644 (file)
@@ -1002,38 +1002,6 @@ static int month_days[12] = {
        31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
 };
 
-/*
- * This only works for the Gregorian calendar - i.e. after 1752 (in the UK)
- */
-void GregorianDay(struct rtc_time * tm)
-{
-       int leapsToDate;
-       int lastYear;
-       int day;
-       int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
-
-       lastYear = tm->tm_year - 1;
-
-       /*
-        * Number of leap corrections to apply up to end of last year
-        */
-       leapsToDate = lastYear / 4 - lastYear / 100 + lastYear / 400;
-
-       /*
-        * This year is a leap year if it is divisible by 4 except when it is
-        * divisible by 100 unless it is divisible by 400
-        *
-        * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 was
-        */
-       day = tm->tm_mon > 2 && leapyear(tm->tm_year);
-
-       day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] +
-                  tm->tm_mday;
-
-       tm->tm_wday = day % 7;
-}
-EXPORT_SYMBOL_GPL(GregorianDay);
-
 void to_tm(int tim, struct rtc_time * tm)
 {
        register int    i;
@@ -1064,9 +1032,9 @@ void to_tm(int tim, struct rtc_time * tm)
        tm->tm_mday = day + 1;
 
        /*
-        * Determine the day of week
+        * No-one uses the day of the week.
         */
-       GregorianDay(tm);
+       tm->tm_wday = -1;
 }
 EXPORT_SYMBOL(to_tm);
 
index b4a369dac3a8aea479580187f7ace7fbe5ce8704..81799d70a1eeb1bb26cf38cab5fafab35cf94f53 100644 (file)
@@ -77,7 +77,7 @@ void maple_get_rtc_time(struct rtc_time *tm)
        if ((tm->tm_year + 1900) < 1970)
                tm->tm_year += 100;
 
-       GregorianDay(tm);
+       tm->tm_wday = -1;
 }
 
 int maple_set_rtc_time(struct rtc_time *tm)
index 37dbee15769fdcb42bc9271e9de81991a79f1ffd..1b149c92fca166429e59dc72b55bcbfe7393d930 100644 (file)
@@ -31,8 +31,7 @@ static void opal_to_tm(u32 y_m_d, u64 h_m_s_ms, struct rtc_time *tm)
        tm->tm_hour     = bcd2bin((h_m_s_ms >> 56) & 0xff);
        tm->tm_min      = bcd2bin((h_m_s_ms >> 48) & 0xff);
        tm->tm_sec      = bcd2bin((h_m_s_ms >> 40) & 0xff);
-
-        GregorianDay(tm);
+       tm->tm_wday     = -1;
 }
 
 unsigned long __init opal_get_boot_time(void)
index df39ce02a99d33f9b5c606b187ab374567290dae..9c18d6fd8107599914558b0d3fe87a80ac38fb1c 100644 (file)
@@ -40,7 +40,7 @@ static void opal_to_tm(u32 y_m_d, u64 h_m_s_ms, struct rtc_time *tm)
        tm->tm_min  = bcd2bin((h_m_s_ms >> 48) & 0xff);
        tm->tm_sec  = bcd2bin((h_m_s_ms >> 40) & 0xff);
 
-       GregorianDay(tm);
+       tm->tm_wday = -1;
 }
 
 static void tm_to_opal(struct rtc_time *tm, u32 *y_m_d, u64 *h_m_s_ms)