From 08e8161f517d70b12a2acbe06831c68d52f1d2f1 Mon Sep 17 00:00:00 2001 From: Yuanyuan Zhao Date: Thu, 21 Apr 2022 15:38:28 +0800 Subject: [PATCH] hv: add time modification of vrtc VRTC for hv used to ignore writes to vRTC register. This patch add time modification to vRTC. Add base RTC time and TSC offset to get the current time. Convert current time to vRTC register values (`struct rtcdev`). Then modify a register, and calculate a new time. Get RTC offset by substrcting new time from current time. Thereafter, add RTC offset also when get current time. Then user can get the modified time. Tracked-On: #7440 Signed-off-by: Yuanyuan Zhao Reviewed-by: Junjie Mao --- hypervisor/dm/vrtc.c | 15 ++++++++++++++- hypervisor/include/dm/vrtc.h | 2 ++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/hypervisor/dm/vrtc.c b/hypervisor/dm/vrtc.c index 4e4ade7b4..1ca20294a 100644 --- a/hypervisor/dm/vrtc.c +++ b/hypervisor/dm/vrtc.c @@ -379,7 +379,7 @@ static time_t vrtc_get_current_time(struct acrn_vrtc *vrtc) if (vrtc->base_rtctime > 0) { offset = (cpu_ticks() - vrtc->base_tsc) / (get_tsc_khz() * 1000U); - second = vrtc->base_rtctime + (time_t)offset; + second = vrtc->base_rtctime + vrtc->offset_rtctime + (time_t)offset; } return second; } @@ -527,7 +527,9 @@ static bool vrtc_read(struct acrn_vcpu *vcpu, uint16_t addr, __unused size_t wid static bool vrtc_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t width, uint32_t value) { + time_t current, after; struct acrn_vrtc *vrtc = &vcpu->vm->vrtc; + uint8_t mask = 0xFFU; if ((width == 1U) && (addr == CMOS_ADDR_PORT)) { vrtc->addr = (uint8_t)(value & 0x7FU); @@ -552,7 +554,18 @@ static bool vrtc_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t width, *((uint8_t *)&vrtc->rtcdev + vrtc->addr) = (uint8_t)(value & 0x7FU); RTC_DEBUG("RTC alarm reg(%d) set to %#x (ignored)\n", vrtc->addr, value); break; + case RTC_SEC: + /* + * High order bit of 'seconds' is readonly. + */ + mask = 0x7FU; + /* FALLTHRU */ default: + RTC_DEBUG("RTC offset %#x set to %#x\n", vrtc->addr, value); + *((uint8_t *)&vrtc->rtcdev + vrtc->addr) = (uint8_t)(value & mask); + current = vrtc_get_current_time(vrtc); + after = rtc_to_secs(vrtc); + vrtc->offset_rtctime += after - current; break; } } diff --git a/hypervisor/include/dm/vrtc.h b/hypervisor/include/dm/vrtc.h index fff2559d2..b760ce445 100644 --- a/hypervisor/include/dm/vrtc.h +++ b/hypervisor/include/dm/vrtc.h @@ -34,6 +34,8 @@ struct acrn_vrtc { uint32_t addr; /* RTC register to read or write */ time_t base_rtctime; /* Base time calulated from physical rtc register. */ + time_t offset_rtctime; /* RTC offset against base time. */ + uint64_t base_tsc; /* Base tsc value */ struct rtcdev rtcdev; /* RTC register */