]> git.baikalelectronics.ru Git - kernel.git/commit
rtc: mc146818: Prevent reading garbage
authorThomas Gleixner <tglx@linutronix.de>
Sun, 6 Dec 2020 21:46:14 +0000 (22:46 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Fri, 11 Dec 2020 09:40:52 +0000 (10:40 +0100)
commit05a0302c35481e9b47fb90ba40922b0a4cae40d8
tree7db10222ad1336406d49830cd504e2767164f227
parentfef92cd2bc04c64bb3743d40c0b4be47aedf9e23
rtc: mc146818: Prevent reading garbage

The MC146818 driver is prone to read garbage from the RTC. There are
several issues all related to the update cycle of the MC146818. The chip
increments seconds obviously once per second and indicates that by a bit in
a register. The bit goes high 244us before the actual update starts. During
the update the readout of the time values is undefined.

The code just checks whether the update in progress bit (UIP) is set before
reading the clock. If it's set it waits arbitrary 20ms before retrying,
which is ample because the maximum update time is ~2ms.

But this check does not guarantee that the UIP bit goes high and the actual
update happens during the readout. So the following can happen

 0.997         UIP = False
   -> Interrupt/NMI/preemption
 0.998        UIP -> True
 0.999        Readout <- Undefined

To prevent this rework the code so it checks UIP before and after the
readout and if set after the readout try again.

But that's not enough to cover the following:

 0.997         UIP = False
         Readout seconds
   -> NMI (or vCPU scheduled out)
 0.998        UIP -> True
         update completes
       UIP -> False
 1.000        Readout minutes,....
         UIP check succeeds

That can make the readout wrong up to 59 seconds.

To prevent this, read the seconds value before the first UIP check,
validate it after checking UIP and after reading out the rest.

It's amazing that the original i386 code had this actually correct and
the generic implementation of the MC146818 driver got it wrong in 2002 and
it stayed that way until today.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Link: https://lore.kernel.org/r/20201206220541.594826678@linutronix.de
drivers/rtc/rtc-mc146818-lib.c