summaryrefslogtreecommitdiff
path: root/include/hw/rtc
diff options
context:
space:
mode:
authorJessica Clarke <jrtc27@jrtc27.com>2020-07-18 01:49:34 +0100
committerAlistair Francis <alistair.francis@wdc.com>2020-07-22 09:39:46 -0700
commit8380b3a453c38f040e7ca2105418802344cc23d0 (patch)
tree7758a8d91a4f448c8439ca97558083defed93f90 /include/hw/rtc
parent3cbc8970f55c87cb58699b6dc8fe42998bc79dc0 (diff)
downloadqemu-8380b3a453c38f040e7ca2105418802344cc23d0.zip
goldfish_rtc: Fix non-atomic read behaviour of TIME_LOW/TIME_HIGH
The specification says: 0x00 TIME_LOW R: Get current time, then return low-order 32-bits. 0x04 TIME_HIGH R: Return high 32-bits from previous TIME_LOW read. ... To read the value, the kernel must perform an IO_READ(TIME_LOW), which returns an unsigned 32-bit value, before an IO_READ(TIME_HIGH), which returns a signed 32-bit value, corresponding to the higher half of the full value. However, we were just returning the current time for both. If the guest is unlucky enough to read TIME_LOW and TIME_HIGH either side of an overflow of the lower half, it will see time be in the future, before jumping backwards on the next read, and Linux currently relies on the atomicity guaranteed by the spec so is affected by this. Fix this violation of the spec by caching the correct value for TIME_HIGH whenever TIME_LOW is read, and returning that value for any TIME_HIGH read. Signed-off-by: Jessica Clarke <jrtc27@jrtc27.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20200718004934.83174-1-jrtc27@jrtc27.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Diffstat (limited to 'include/hw/rtc')
-rw-r--r--include/hw/rtc/goldfish_rtc.h1
1 files changed, 1 insertions, 0 deletions
diff --git a/include/hw/rtc/goldfish_rtc.h b/include/hw/rtc/goldfish_rtc.h
index 16f9f9e29d..9bd8924f5f 100644
--- a/include/hw/rtc/goldfish_rtc.h
+++ b/include/hw/rtc/goldfish_rtc.h
@@ -41,6 +41,7 @@ typedef struct GoldfishRTCState {
uint32_t alarm_running;
uint32_t irq_pending;
uint32_t irq_enabled;
+ uint32_t time_high;
} GoldfishRTCState;
#endif