[PATCH 1/3] powerpc: mac: fix rtc read functions

Mathieu Malaterre malat at debian.org
Tue Jun 19 05:10:06 AEST 2018


On Mon, Jun 18, 2018 at 4:07 PM Arnd Bergmann <arnd at arndb.de> wrote:
>
> As Mathieu pointed out, my conversion to time64_t was incorrect and resulted
> in negative times to be read from the RTC. The problem is that during the
> conversion from a byte array to a time64_t, the 'unsigned char' variable
> holding the top byte gets turned into a negative signed 32-bit integer
> before being assigned to the 64-bit variable for any times after 1972.
>
> This changes the logic to cast to an unsigned 32-bit number first for
> the Macintosh time and then convert that to the Unix time, which then gives
> us a time in the documented 1904..2040 year range. I decided not to use
> the longer 1970..2106 range that other drivers use, for consistency with
> the literal interpretation of the register, but that could be easily
> changed if we decide we want to support any Mac after 2040.
>
> Just to be on the safe side, I'm also adding a WARN_ON that will trigger
> if either the year 2040 has come and is observed by this driver, or we
> run into an RTC that got set back to a pre-1970 date for some reason
> (the two are indistinguishable).
>
> The same code exists in arch/m68k/ and is patched in an identical way now
> in a separate patch.
>
> Fixes: 5bfd643583b2 ("powerpc: use time64_t in read_persistent_clock")
> Reported-by: Mathieu Malaterre <malat at debian.org>
> Signed-off-by: Arnd Bergmann <arnd at arndb.de>
> ---
>  arch/powerpc/platforms/powermac/time.c | 21 ++++++++++++++++-----
>  1 file changed, 16 insertions(+), 5 deletions(-)
>
> diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c
> index 7c968e46736f..173a80630169 100644
> --- a/arch/powerpc/platforms/powermac/time.c
> +++ b/arch/powerpc/platforms/powermac/time.c
> @@ -42,7 +42,11 @@
>  #define DBG(x...)
>  #endif
>
> -/* Apparently the RTC stores seconds since 1 Jan 1904 */
> +/*
> + * Offset between Unix time (1970-based) and Mac time (1904-based). Cuda and PMU
> + * times wrap in 2040. If we need to handle later times, the read_time functions
> + * need to be changed to interpret wrapped times as post-2040.
> + */
>  #define RTC_OFFSET     2082844800
>
>  /*
> @@ -97,8 +101,11 @@ static time64_t cuda_get_time(void)
>         if (req.reply_len != 7)
>                 printk(KERN_ERR "cuda_get_time: got %d byte reply\n",
>                        req.reply_len);
> -       now = (req.reply[3] << 24) + (req.reply[4] << 16)
> -               + (req.reply[5] << 8) + req.reply[6];
> +       now = (u32)((req.reply[3] << 24) + (req.reply[4] << 16) +
> +                   (req.reply[5] << 8) + req.reply[6]);
> +       /* it's either after year 2040, or the RTC has gone backwards */
> +       WARN_ON(now < RTC_OFFSET);
> +
>         return now - RTC_OFFSET;
>  }
>
> @@ -140,8 +147,12 @@ static time64_t pmu_get_time(void)
>         if (req.reply_len != 4)
>                 printk(KERN_ERR "pmu_get_time: got %d byte reply from PMU\n",
>                        req.reply_len);
> -       now = (req.reply[0] << 24) + (req.reply[1] << 16)
> -               + (req.reply[2] << 8) + req.reply[3];
> +       now = (u32)((req.reply[0] << 24) + (req.reply[1] << 16) +
> +                   (req.reply[2] << 8) + req.reply[3]);
> +
> +       /* it's either after year 2040, or the RTC has gone backwards */
> +       WARN_ON(now < RTC_OFFSET);
> +
>         return now - RTC_OFFSET;
>  }

Sadly, trying again today does not work anymore. Adding some printk
just before WARN_ON:

+printk(KERN_ERR " rtc DBG pmu_get_time1: %lld %d %lld \n", now,
RTC_OFFSET, now - RTC_OFFSET );
+printk(KERN_ERR " rtc DBG pmu_get_time2: %x %x %x %x %d \n",
req.reply[0], req.reply[1], req.reply[2], req.reply[3] ,
req.reply_len);

leads to:

[    0.000000]  rtc DBG pmu_get_time1: 14096662 2082844800 -2068748138
[    0.000000]  rtc DBG pmu_get_time2: 0 d7 19 16 4
[    0.000000] WARNING: CPU: 0 PID: 0 at
../arch/powerpc/platforms/powermac/time.c:158 pmu_get_time+0x11c/0x16c
[    0.000000] Modules linked in:
[    0.000000] CPU: 0 PID: 0 Comm: swapper Not tainted 4.17.0+ #8
[    0.000000] NIP:  c0035658 LR: c0035640 CTR: c00d4a5c
[    0.000000] REGS: c0cf7da0 TRAP: 0700   Not tainted  (4.17.0+)
[    0.000000] MSR:  00021032 <ME,IR,DR,RI>  CR: 84000848  XER: 00000000
[    0.000000]
               GPR00: c0035640 c0cf7e50 c0a41bd0 00000025 00000001
00000051 c0d56430 00000000
               GPR08: 00000051 00000001 c0aa4b38 00000004 24000842
00000000 ffbbf4c0 0013da1c
               GPR16: 0013da18 0013da20 00000000 00000000 00b81044
01696028 01697e02 40140000
               GPR24: 00000000 00d71000 c09debec dfff1120 000001a4
00d71916 ffffffff 84b16896
[    0.000000] NIP [c0035658] pmu_get_time+0x11c/0x16c
[    0.000000] LR [c0035640] pmu_get_time+0x104/0x16c
[    0.000000] Call Trace:
[    0.000000] [c0cf7e50] [c0035640] pmu_get_time+0x104/0x16c (unreliable)
[    0.000000] [c0cf7ed0] [c00113fc] read_persistent_clock64+0x78/0x1ac
[    0.000000] [c0cf7f30] [c09ad470] timekeeping_init+0x24/0x2f4
[    0.000000] [c0cf7fc0] [c09986f0] start_kernel+0x34c/0x490
[    0.000000] [c0cf7ff0] [00003444] 0x3444
[    0.000000] Instruction dump:
[    0.000000] 88e1002f 3863404c 88c1002e 88a1002d 8881002c 4809baf1
3d207c25 6129b07f
[    0.000000] 7f9d4840 39200001 409d0008 39200000 <0f090000> 4bffff20
3c60c0c1 7fe4fb78
[    0.000000] random: get_random_bytes called from
print_oops_end_marker+0x6c/0x90 with crng_init=0
[    0.000000] ---[ end trace 93a1b37c50fb7a33 ]---


and then later on :

[    5.535354]  rtc DBG pmu_get_time1: 14096667 2082844800 -2068748133
[    5.539988]  rtc DBG pmu_get_time2: 0 d7 19 1b 4
[    5.544477] WARNING: CPU: 0 PID: 1 at
../arch/powerpc/platforms/powermac/time.c:158 pmu_get_time+0x11c/0x16c
[    5.553536] Modules linked in:
[    5.558076] CPU: 0 PID: 1 Comm: swapper Tainted: G        W
4.17.0+ #8
[    5.562769] NIP:  c0035658 LR: c0035640 CTR: c00d4a5c
[    5.567437] REGS: df4e7a90 TRAP: 0700   Tainted: G        W
 (4.17.0+)
[    5.572201] MSR:  00029032 <EE,ME,IR,DR,RI>  CR: 88008288  XER: 00000000
[    5.577028]
               GPR00: c0035640 df4e7b40 df4e8000 00000025 00000001
00000344 00000400 00000000
               GPR08: 00000003 00000001 c0aa4b38 00000000 28008282
00000000 c09dfc4c c09dfc28
               GPR16: 00000690 c0aedae0 c0aee64c c0aecf50 00000054
c0ae7488 c0aea0f4 00000000
               GPR24: c0d70000 c0a85850 c086fc74 df4e7c5c df4e7ce8
00d7191b ffffffff 84b1689b
[    5.601871] NIP [c0035658] pmu_get_time+0x11c/0x16c
[    5.606952] LR [c0035640] pmu_get_time+0x104/0x16c
[    5.612042] Call Trace:
[    5.617079] [df4e7b40] [c0035640] pmu_get_time+0x104/0x16c (unreliable)
[    5.622297] [df4e7bc0] [c003572c] pmac_get_rtc_time+0x34/0x4c
[    5.627509] [df4e7bd0] [c001076c] rtc_generic_get_time+0x2c/0x40
[    5.632740] [df4e7be0] [c0611fb8] __rtc_read_time+0x70/0x13c
[    5.637977] [df4e7c00] [c06120f0] rtc_read_time+0x6c/0x130
[    5.643230] [df4e7c30] [c0613324] __rtc_read_alarm+0x34/0x684
[    5.648503] [df4e7ce0] [c060fe18] rtc_device_register+0x88/0x218
[    5.653804] [df4e7d40] [c061000c] devm_rtc_device_register+0x64/0xc4
[    5.659127] [df4e7d60] [c09d2630] generic_rtc_probe+0x50/0x78
[    5.664457] [df4e7d70] [c055eefc] platform_drv_probe+0xa8/0x128
[    5.669735] [df4e7d90] [c055a780] driver_probe_device+0x354/0x6fc
[    5.674905] [df4e7dd0] [c055acc8] __driver_attach+0x1a0/0x22c
[    5.679971] [df4e7df0] [c05565c8] bus_for_each_dev+0x84/0xdc
[    5.685017] [df4e7e20] [c0558e78] bus_add_driver+0x188/0x348
[    5.690021] [df4e7e40] [c055c20c] driver_register+0xa0/0x18c
[    5.694982] [df4e7e50] [c055f3a8] __platform_driver_probe+0x8c/0x198
[    5.699918] [df4e7e70] [c0005800] do_one_initcall+0x64/0x280
[    5.704726] [df4e7ee0] [c0998bd8] kernel_init_freeable+0x3a4/0x444
[    5.709433] [df4e7f30] [c00049f8] kernel_init+0x24/0x118
[    5.713995] [df4e7f40] [c001b1c4] ret_from_kernel_thread+0x14/0x1c
[    5.718536] Instruction dump:
[    5.723041] 88e1002f 3863404c 88c1002e 88a1002d 8881002c 4809baf1
3d207c25 6129b07f
[    5.727651] 7f9d4840 39200001 409d0008 39200000 <0f090000> 4bffff20
3c60c0c1 7fe4fb78
[    5.732196] ---[ end trace 93a1b37c50fb7a34 ]---
[    5.736768] ================================================================================
[    5.741519] UBSAN: Undefined behaviour in ../drivers/rtc/rtc-lib.c:87:22
[    5.746295] signed integer overflow:
[    5.751002] 1193026 * 3600 cannot be represented in type 'int'
[    5.755739] CPU: 0 PID: 1 Comm: swapper Tainted: G        W
4.17.0+ #8
[    5.760529] Call Trace:
[    5.765124] [df4e7b00] [c04817ec] ubsan_epilogue+0x18/0x4c (unreliable)
[    5.769871] [df4e7b10] [c048218c] handle_overflow+0xbc/0xdc
[    5.774580] [df4e7b90] [c060e27c] rtc_time64_to_tm+0x344/0x388
[    5.779264] [df4e7bd0] [c001076c] rtc_generic_get_time+0x2c/0x40
[    5.783841] [df4e7be0] [c0611fb8] __rtc_read_time+0x70/0x13c
[    5.788395] [df4e7c00] [c06120f0] rtc_read_time+0x6c/0x130
[    5.792929] [df4e7c30] [c0613324] __rtc_read_alarm+0x34/0x684
[    5.797415] [df4e7ce0] [c060fe18] rtc_device_register+0x88/0x218
[    5.801895] [df4e7d40] [c061000c] devm_rtc_device_register+0x64/0xc4
[    5.806395] [df4e7d60] [c09d2630] generic_rtc_probe+0x50/0x78
[    5.810889] [df4e7d70] [c055eefc] platform_drv_probe+0xa8/0x128
[    5.815405] [df4e7d90] [c055a780] driver_probe_device+0x354/0x6fc
[    5.819929] [df4e7dd0] [c055acc8] __driver_attach+0x1a0/0x22c
[    5.824440] [df4e7df0] [c05565c8] bus_for_each_dev+0x84/0xdc
[    5.828922] [df4e7e20] [c0558e78] bus_add_driver+0x188/0x348
[    5.833366] [df4e7e40] [c055c20c] driver_register+0xa0/0x18c
[    5.837789] [df4e7e50] [c055f3a8] __platform_driver_probe+0x8c/0x198
[    5.842244] [df4e7e70] [c0005800] do_one_initcall+0x64/0x280
[    5.846700] [df4e7ee0] [c0998bd8] kernel_init_freeable+0x3a4/0x444
[    5.851186] [df4e7f30] [c00049f8] kernel_init+0x24/0x118
[    5.855656] [df4e7f40] [c001b1c4] ret_from_kernel_thread+0x14/0x1c
[    5.860171] ================================================================================
[    5.864998] device: 'rtc0': device_add



> --
> 2.9.0
>


More information about the Linuxppc-dev mailing list