hv: calibrate vrtc when modify physical time

For Service VM modify physical rtc time and vrtc will calibrate
time by read physical rtc. So when Service VM modify physical
time, calibrate all vrtc.

Tracked-On: #7440
Signed-off-by: Yuanyuan Zhao <yuanyuan.zhao@linux.intel.com>
Reviewed-by: Junjie Mao <junjie.mao@intel.com>
This commit is contained in:
Yuanyuan Zhao 2022-04-26 10:33:56 +08:00 committed by acrnsi-robot
parent 4bad719fd3
commit 145a56d448

View File

@ -40,6 +40,9 @@
# define RTC_DEBUG(format, ...) do { } while (false)
#endif
static time_t vrtc_get_physical_rtc_time(struct acrn_vrtc *vrtc);
static void vrtc_update_basetime(time_t physical_time, time_t offset);
struct clktime {
uint32_t year; /* year (4 digit year) */
uint32_t mon; /* month (1 - 12) */
@ -524,6 +527,12 @@ static bool vrtc_read(struct acrn_vcpu *vcpu, uint16_t addr, __unused size_t wid
return ret;
}
static inline bool vrtc_is_time_register(uint32_t offset)
{
return ((offset == RTC_SEC) || (offset == RTC_MIN) || (offset == RTC_HRS) || (offset == RTC_DAY)
|| (offset == RTC_MONTH) || (offset == RTC_YEAR) || (offset == RTC_CENTURY));
}
/**
* @pre vcpu != NULL
* @pre vcpu->vm != NULL
@ -533,13 +542,23 @@ static bool vrtc_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t width,
{
time_t current, after;
struct acrn_vrtc *vrtc = &vcpu->vm->vrtc;
struct acrn_vrtc temp_vrtc;
bool is_time_register;
uint8_t mask = 0xFFU;
if ((width == 1U) && (addr == CMOS_ADDR_PORT)) {
vrtc->addr = (uint8_t)(value & 0x7FU);
} else {
if (is_service_vm(vcpu->vm)) {
cmos_set_reg_val(vrtc->addr, (uint8_t)(value & 0xFFU));
is_time_register = vrtc_is_time_register(vrtc->addr);
if (is_time_register) {
current = vrtc_get_physical_rtc_time(&temp_vrtc);
}
cmos_set_reg_val(vcpu->vm->vrtc.addr, (uint8_t)(value & 0xFFU));
if (is_time_register) {
after = vrtc_get_physical_rtc_time(&temp_vrtc);
vrtc_update_basetime(after, current - after);
}
} else {
switch (vrtc->addr) {
case RTC_STATUSA: