1 /*
2  * Copyright (c) 2014, Neel Natu (neel@freebsd.org)
3  * Copyright (c) 2024 Intel Corporation.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice unmodified, this list of conditions, and the following
11  *    disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <asm/guest/vm.h>
29 #include <asm/io.h>
30 #include <asm/tsc.h>
31 #include <vrtc.h>
32 #include <logmsg.h>
33 #include <vm_event.h>
34 
35 #include "mc146818rtc.h"
36 
37 /**
38  * @addtogroup vp-dm_vperipheral
39  *
40  * @{
41  */
42 
43 /**
44  * @file
45  * @brief Implementation of virtual RTC device.
46  *
47  * This file provides the implementation of the virtual RTC device. The virtual RTC device is used to provide the RTC
48  * service to the guest VMs. It is a part of the virtual peripheral devices.
49  */
50 
51 /* #define DEBUG_RTC */
52 #ifdef DEBUG_RTC
53 # define RTC_DEBUG  pr_info
54 #else
55 # define RTC_DEBUG(format, ...)      do { } while (false)
56 #endif
57 
58 static time_t vrtc_get_physical_rtc_time(struct acrn_vrtc *vrtc);
59 static void vrtc_update_basetime(time_t physical_time, time_t offset);
60 
61 struct clktime {
62 	uint32_t	year;	/* year (4 digit year) */
63 	uint32_t	mon;	/* month (1 - 12) */
64 	uint32_t	day;	/* day (1 - 31) */
65 	uint32_t	hour;	/* hour (0 - 23) */
66 	uint32_t	min;	/* minute (0 - 59) */
67 	uint32_t	sec;	/* second (0 - 59) */
68 	uint32_t	dow;	/* day of week (0 - 6; 0 = Sunday) */
69 };
70 
71 static spinlock_t vrtc_rebase_lock = { .head = 0U, .tail = 0U };
72 
73 #define POSIX_BASE_YEAR	1970
74 #define SECDAY		(24 * 60 * 60)
75 #define SECYR		(SECDAY * 365)
76 #define VRTC_BROKEN_TIME	((time_t)-1)
77 
78 #define FEBRUARY	2U
79 
80 static const uint32_t month_days[12] = {
81 	31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U
82 };
83 
84 /*
85  * This inline avoids some unnecessary modulo operations
86  * as compared with the usual macro:
87  *   ( ((year % 4) == 0 &&
88  *      (year % 100) != 0) ||
89  *     ((year % 400) == 0) )
90  * It is otherwise equivalent.
91  */
leapyear(uint32_t year)92 static inline uint32_t leapyear(uint32_t year)
93 {
94 	uint32_t rv = 0U;
95 
96 	if ((year & 3U) == 0) {
97 		rv = 1U;
98 		if ((year % 100U) == 0) {
99 			rv = 0U;
100 			if ((year % 400U) == 0) {
101 				rv = 1U;
102 			}
103 		}
104 	}
105 	return rv;
106 }
107 
days_in_year(uint32_t year)108 static inline uint32_t days_in_year(uint32_t year)
109 {
110         return leapyear(year) ? 366U : 365U;
111 }
112 
days_in_month(uint32_t year,uint32_t month)113 static inline uint32_t days_in_month(uint32_t year, uint32_t month)
114 {
115         return month_days[(month) - 1U] + ((month == FEBRUARY) ? leapyear(year) : 0U);
116 }
117 
118 /*
119  * Day of week. Days are counted from 1/1/1970, which was a Thursday.
120  */
day_of_week(uint32_t days)121 static inline uint32_t day_of_week(uint32_t days)
122 {
123         return ((days) + 4U) % 7U;
124 }
125 
126 uint8_t const bin2bcd_data[] = {
127 	0x00U, 0x01U, 0x02U, 0x03U, 0x04U, 0x05U, 0x06U, 0x07U, 0x08U, 0x09U,
128 	0x10U, 0x11U, 0x12U, 0x13U, 0x14U, 0x15U, 0x16U, 0x17U, 0x18U, 0x19U,
129 	0x20U, 0x21U, 0x22U, 0x23U, 0x24U, 0x25U, 0x26U, 0x27U, 0x28U, 0x29U,
130 	0x30U, 0x31U, 0x32U, 0x33U, 0x34U, 0x35U, 0x36U, 0x37U, 0x38U, 0x39U,
131 	0x40U, 0x41U, 0x42U, 0x43U, 0x44U, 0x45U, 0x46U, 0x47U, 0x48U, 0x49U,
132 	0x50U, 0x51U, 0x52U, 0x53U, 0x54U, 0x55U, 0x56U, 0x57U, 0x58U, 0x59U,
133 	0x60U, 0x61U, 0x62U, 0x63U, 0x64U, 0x65U, 0x66U, 0x67U, 0x68U, 0x69U,
134 	0x70U, 0x71U, 0x72U, 0x73U, 0x74U, 0x75U, 0x76U, 0x77U, 0x78U, 0x79U,
135 	0x80U, 0x81U, 0x82U, 0x83U, 0x84U, 0x85U, 0x86U, 0x87U, 0x88U, 0x89U,
136 	0x90U, 0x91U, 0x92U, 0x93U, 0x94U, 0x95U, 0x96U, 0x97U, 0x98U, 0x99U
137 };
138 
139 /*
140  * @pre val < 100
141  */
rtcset(struct rtcdev * rtc,uint32_t val)142 static inline uint8_t rtcset(struct rtcdev *rtc, uint32_t val)
143 {
144 	return ((rtc->reg_b & RTCSB_BCD) ? val : bin2bcd_data[val]);
145 }
146 
147 /*
148  * Get rtc time register binary value.
149  * If BCD data mode is enabled, translate BCD to binary.
150  */
rtcget(const struct rtcdev * rtc,uint8_t val,uint32_t * retval)151 static int32_t rtcget(const struct rtcdev *rtc, uint8_t val, uint32_t *retval)
152 {
153 	uint8_t upper, lower;
154 	int32_t errno = 0;
155 
156 	if (rtc->reg_b & RTCSB_BCD) {
157 		*retval = val;
158 	} else {
159 		lower = val & 0xfU;
160 		upper = (val >> 4) & 0xfU;
161 
162 		if ((lower > 9U) || (upper > 9U)) {
163 			errno = -EINVAL;
164 		} else {
165 			*retval = upper * 10U + lower;
166 		}
167 	}
168 	return errno;
169 }
170 
171 /*
172  * Translate clktime (such as year, month, day) to time_t.
173  */
clk_ct_to_ts(struct clktime * ct,time_t * sec)174 static int32_t clk_ct_to_ts(struct clktime *ct, time_t *sec)
175 {
176 	uint32_t i, year, days;
177 	int32_t err = 0;
178 
179 	year = ct->year;
180 
181 	/* Sanity checks. */
182 	if ((ct->mon < 1U) || (ct->mon > 12U) || (ct->day < 1U) ||
183 			(ct->day > days_in_month(year, ct->mon)) ||
184 			(ct->hour > 23U) ||  (ct->min > 59U) || (ct->sec > 59U) ||
185 			(year < POSIX_BASE_YEAR) || (year > 2037U)) {
186 		/* time_t overflow */
187 		err = -EINVAL;
188 	} else {
189 		/*
190 		 * Compute days since start of time
191 		 * First from years, then from months.
192 		 */
193 		days = 0U;
194 		for (i = POSIX_BASE_YEAR; i < year; i++) {
195 			days += days_in_year(i);
196 		}
197 
198 		/* Months */
199 		for (i = 1; i < ct->mon; i++) {
200 			days += days_in_month(year, i);
201 		}
202 		days += (ct->day - 1);
203 
204 		*sec = (((time_t)days * 24 + ct->hour) * 60 + ct->min) * 60 + ct->sec;
205 	}
206 	return err;
207 }
208 
209 /*
210  * Translate time_t to clktime (such as year, month, day)
211  */
clk_ts_to_ct(time_t secs,struct clktime * ct)212 static int32_t clk_ts_to_ct(time_t secs, struct clktime *ct)
213 {
214 	uint32_t i, year, days;
215 	time_t rsec;	/* remainder seconds */
216 	int32_t err = 0;
217 
218 	days = secs / SECDAY;
219 	rsec = secs % SECDAY;
220 
221 	ct->dow = day_of_week(days);
222 
223 	/* Substract out whole years, counting them in i. */
224 	for (year = POSIX_BASE_YEAR; days >= days_in_year(year); year++) {
225 		days -= days_in_year(year);
226 	}
227 	ct->year = year;
228 
229 	/* Substract out whole months, counting them in i. */
230 	for (i = 1; days >= days_in_month(year, i); i++) {
231 		days -= days_in_month(year, i);
232 	}
233 	ct->mon = i;
234 
235 	/* Days are what is left over (+1) from all that. */
236 	ct->day = days + 1;
237 
238 	/* Hours, minutes, seconds are easy */
239 	ct->hour = rsec / 3600U;
240 	rsec = rsec % 3600U;
241 	ct->min  = rsec / 60U;
242 	rsec = rsec % 60U;
243 	ct->sec  = rsec;
244 
245 	/* time_t is defined as int32_t, so year should not be more than 2037. */
246 	if ((ct->mon > 12U) || (ct->year > 2037) || (ct->day > days_in_month(ct->year, ct->mon))) {
247 		pr_err("Invalid vRTC param mon %d, year %d, day %d\n", ct->mon, ct->year, ct->day);
248 		err = -EINVAL;
249 	}
250 	return err;
251 }
252 
253 /*
254  * Calculate second value from rtcdev register info which save in vrtc.
255  */
rtc_to_secs(const struct acrn_vrtc * vrtc)256 static time_t rtc_to_secs(const struct acrn_vrtc *vrtc)
257 {
258 	struct clktime ct;
259 	time_t second = VRTC_BROKEN_TIME;
260 	const struct rtcdev *rtc= &vrtc->rtcdev;
261 	uint32_t hour = 0, pm = 0;
262 	uint32_t century = 0, year = 0;
263 
264 	do {
265 		if ((rtcget(rtc, rtc->sec, &ct.sec) < 0) || (rtcget(rtc, rtc->min, &ct.min) < 0) ||
266 				(rtcget(rtc, rtc->day_of_month, &ct.day) < 0) ||
267 				(rtcget(rtc, rtc->month, &ct.mon) < 0) || (rtcget(rtc, rtc->year, &year) < 0) ||
268 				(rtcget(rtc, rtc->century, &century) < 0)) {
269 			pr_err("Invalid RTC sec %#x hour %#x day %#x mon %#x year %#x century %#x\n",
270 					rtc->sec, rtc->min, rtc->day_of_month, rtc->month,
271 					rtc->year, rtc->century);
272 			break;
273 		}
274 
275 		/*
276 		 * If 12 hour format is inuse, translate it to 24 hour format here.
277 		 */
278 		pm = 0;
279 		hour = rtc->hour;
280 		if ((rtc->reg_b & RTCSB_24HR) == 0) {
281 			if (hour & 0x80U) {
282 				hour &= ~0x80U;
283 				pm = 1;
284 			}
285 		}
286 		if (rtcget(rtc, hour, &ct.hour) != 0) {
287 			pr_err("Invalid RTC hour %#x\n", rtc->hour);
288 			break;
289 		}
290 		if ((rtc->reg_b & RTCSB_24HR) == 0) {
291 			if ((ct.hour >= 1) && (ct.hour <= 12)) {
292 				/*
293 				 * Convert from 12-hour format to internal 24-hour
294 				 * representation as follows:
295 				 *
296 				 *    12-hour format		ct.hour
297 				 *	12	AM		0
298 				 *	1 - 11	AM		1 - 11
299 				 *	12	PM		12
300 				 *	1 - 11	PM		13 - 23
301 				 */
302 				if (ct.hour == 12) {
303 					ct.hour = 0;
304 				}
305 				if (pm) {
306 					ct.hour += 12;
307 				}
308 			} else {
309 				pr_err("Invalid RTC 12-hour format %#x/%d\n",
310 						rtc->hour, ct.hour);
311 				break;
312 			}
313 		}
314 
315 		/*
316 		 * Ignore 'rtc->dow' because some guests like Linux don't bother
317 		 * setting it at all while others like OpenBSD/i386 set it incorrectly.
318 		 *
319 		 * clock_ct_to_ts() does not depend on 'ct.dow' anyways so ignore it.
320 		 */
321 		ct.dow = -1;
322 
323 		ct.year = century * 100 + year;
324 		if (ct.year < POSIX_BASE_YEAR) {
325 			pr_err("Invalid RTC century %x/%d\n", rtc->century,
326 					ct.year);
327 			break;
328 		}
329 
330 		if (clk_ct_to_ts(&ct, &second) != 0) {
331 			pr_err("Invalid RTC clocktime.date %04d-%02d-%02d\n",
332 					ct.year, ct.mon, ct.day);
333 			pr_err("Invalid RTC clocktime.time %02d:%02d:%02d\n",
334 					ct.hour, ct.min, ct.sec);
335 			break;
336 		}
337 	} while (false);
338 
339 	return second;
340 }
341 
342 /*
343  * Translate second value to rtcdev register info and save it in vrtc.
344  */
secs_to_rtc(time_t rtctime,struct acrn_vrtc * vrtc)345 static void secs_to_rtc(time_t rtctime, struct acrn_vrtc *vrtc)
346 {
347 	struct clktime ct;
348 	struct rtcdev *rtc;
349 	uint32_t hour;
350 
351 	if ((rtctime > 0) && (clk_ts_to_ct(rtctime, &ct) == 0)) {
352 		rtc = &vrtc->rtcdev;
353 		rtc->sec = rtcset(rtc, ct.sec);
354 		rtc->min = rtcset(rtc, ct.min);
355 
356 		if (rtc->reg_b & RTCSB_24HR) {
357 			hour = ct.hour;
358 		} else {
359 			/*
360 			 * Convert to the 12-hour format.
361 			 */
362 			switch (ct.hour) {
363 			case 0:			/* 12 AM */
364 			case 12:		/* 12 PM */
365 				hour = 12;
366 				break;
367 			default:
368 				/*
369 				 * The remaining 'ct.hour' values are interpreted as:
370 				 * [1  - 11] ->  1 - 11 AM
371 				 * [13 - 23] ->  1 - 11 PM
372 				 */
373 				hour = ct.hour % 12;
374 				break;
375 			}
376 		}
377 
378 		rtc->hour = rtcset(rtc, hour);
379 
380 		if (((rtc->reg_b & RTCSB_24HR) == 0) && (ct.hour >= 12)) {
381 			rtc->hour |= 0x80;	    /* set MSB to indicate PM */
382 		}
383 
384 		rtc->day_of_week = rtcset(rtc, ct.dow + 1);
385 		rtc->day_of_month = rtcset(rtc, ct.day);
386 		rtc->month = rtcset(rtc, ct.mon);
387 		rtc->year = rtcset(rtc, ct.year % 100);
388 		rtc->century = rtcset(rtc, ct.year / 100);
389 	}
390 }
391 
392 /*
393  * If the base_rtctime is valid, calculate current time by add tsc offset and offset_rtctime.
394  */
vrtc_get_current_time(struct acrn_vrtc * vrtc)395 static time_t vrtc_get_current_time(struct acrn_vrtc *vrtc)
396 {
397 	uint64_t offset;
398 	time_t second = VRTC_BROKEN_TIME;
399 
400 	spinlock_obtain(&vrtc_rebase_lock);
401 	if (vrtc->base_rtctime > 0) {
402 		offset = (cpu_ticks() - vrtc->base_tsc) / (get_tsc_khz() * 1000U);
403 		second = vrtc->base_rtctime + vrtc->offset_rtctime + (time_t)offset;
404 		if (second < vrtc->last_rtctime) {
405 			second = vrtc->last_rtctime;
406 		} else {
407 			vrtc->last_rtctime = second;
408 		}
409 	}
410 	spinlock_release(&vrtc_rebase_lock);
411 	return second;
412 }
413 
414 #define CMOS_ADDR_PORT		0x70U
415 #define CMOS_DATA_PORT		0x71U
416 
417 static spinlock_t cmos_lock = { .head = 0U, .tail = 0U };
418 
cmos_read(uint8_t addr)419 static uint8_t cmos_read(uint8_t addr)
420 {
421 	pio_write8(addr, CMOS_ADDR_PORT);
422 	return pio_read8(CMOS_DATA_PORT);
423 }
424 
cmos_write(uint8_t addr,uint8_t value)425 static void cmos_write(uint8_t addr, uint8_t value)
426 {
427 	pio_write8(addr, CMOS_ADDR_PORT);
428 	pio_write8(value, CMOS_DATA_PORT);
429 }
430 
cmos_update_in_progress(void)431 static bool cmos_update_in_progress(void)
432 {
433 	return (cmos_read(RTC_STATUSA) & RTCSA_TUP) ? 1 : 0;
434 }
435 
cmos_get_reg_val(uint8_t addr)436 static uint8_t cmos_get_reg_val(uint8_t addr)
437 {
438 	uint8_t reg;
439 	int32_t tries = 2000;
440 
441 	spinlock_obtain(&cmos_lock);
442 
443 	/* Make sure an update isn't in progress */
444 	while (cmos_update_in_progress() && (tries != 0)) {
445 		tries -= 1;
446 	}
447 
448 	reg = cmos_read(addr);
449 
450 	spinlock_release(&cmos_lock);
451 	return reg;
452 }
453 
cmos_set_reg_val(uint8_t addr,uint8_t value)454 static void cmos_set_reg_val(uint8_t addr, uint8_t value)
455 {
456 	int32_t tries = 2000;
457 
458 	spinlock_obtain(&cmos_lock);
459 
460 	/* Make sure an update isn't in progress */
461 	while (cmos_update_in_progress() && (tries != 0)) {
462 		tries -= 1;
463 	}
464 
465 	cmos_write(addr, value);
466 
467 	spinlock_release(&cmos_lock);
468 }
469 
470 #define TRIGGER_ALARM	(RTCIR_ALARM | RTCIR_INT)
471 #define RTC_DELTA	1	/* For RTC and system time may out of sync for no more than 1s */
472 
vrtc_get_reg_c(struct acrn_vrtc * vrtc)473 static uint8_t vrtc_get_reg_c(struct acrn_vrtc *vrtc)
474 {
475 	uint8_t	ret = vrtc->rtcdev.reg_c;
476 	struct rtcdev *rtc = &vrtc->rtcdev;
477 	time_t current, alarm;
478 
479 	if ((rtc->reg_b & RTCSB_AINTR) != 0U) {
480 		current = rtc->hour * 3600 + rtc->min * 60 + rtc->sec;
481 		alarm = rtc->alarm_hour * 3600 + rtc->alarm_min * 60 + rtc->alarm_sec;
482 
483 		if ((current >= (alarm - RTC_DELTA)) && (current <= (alarm + RTC_DELTA))) {
484 			/*
485 			 * Linux RTC driver will trigger alarm interrupt when getting
486 			 * RTC time, and then read the interrupt flag register. If the value was not
487 			 * correct, read failure will occurs. So if alarm interrupt is enabled
488 			 * and rtc time is in alarm time scale, set the interrupt flag. The
489 			 * interrupt is not acturally triggered for driver will read the register
490 			 * proactively.
491 			 */
492 			ret |= TRIGGER_ALARM;
493 		}
494 	}
495 
496 	vrtc->rtcdev.reg_c = 0;
497 	return ret;
498 }
499 
vrtc_set_reg_b(struct acrn_vrtc * vrtc,uint8_t newval)500 static void vrtc_set_reg_b(struct acrn_vrtc *vrtc, uint8_t newval)
501 {
502 	vrtc->rtcdev.reg_b = newval;
503 }
504 
505 /**
506  * @brief Read from the virtual RTC device.
507  *
508  * This function reads the value from the RTC register specified by the address port. To read from the virtual RTC
509  * device, the guest writes the register index to the RTC address port and then reads the register value from the RTC
510  * data port. This function is used to simulate the behavior of reading in a virtualized environment.
511  *
512  * - If the accessed port is CMOS_ADDR_PORT, it will set the value as index cached in last write (0 by default) and
513  *   return.
514  * - If the accessed port is CMOS_DATA_PORT,
515  *   - For Service VM, it will directly read the value from the physical CMOS register.
516  *   - For a non-Service VM, it will return false indicating the read operation failed if the address is greater than
517  *     RTC_CENTURY. Otherwise, the read operation will be emulated.
518  *
519  * @param[inout] vcpu Pointer to the virtual CPU that is reading from the virtual RTC. The value read from the virtual
520  *                    RTC will be stored in the PIO request.
521  * @param[in] addr The address port to read from.
522  * @param[in] width The width of the data to be read. This is not used in this function.
523  *
524  * @return A boolean value indicating whether the read operation is successful.
525  *
526  * @retval true Successfully read from the virtual RTC device.
527  * @retval false Failed to read from the virtual RTC device.
528  *
529  * @pre vcpu != NULL
530  * @pre vcpu->vm != NULL
531  * @pre addr == 0x70U || addr == 0x71U
532  *
533  * @post N/A
534  */
vrtc_read(struct acrn_vcpu * vcpu,uint16_t addr,__unused size_t width)535 static bool vrtc_read(struct acrn_vcpu *vcpu, uint16_t addr, __unused size_t width)
536 {
537 	uint8_t offset;
538 	time_t current;
539 	struct acrn_vrtc *vrtc = &vcpu->vm->vrtc;
540 	struct acrn_pio_request *pio_req = &vcpu->req.reqs.pio_request;
541 	struct acrn_vm *vm = vcpu->vm;
542 	bool ret = true;
543 
544 	offset = vrtc->addr;
545 
546 	if (addr == CMOS_ADDR_PORT) {
547 		pio_req->value = offset;
548 	} else {
549 		if (is_service_vm(vm)) {
550 			pio_req->value = cmos_get_reg_val(offset);
551 		} else {
552 			if (offset <= RTC_CENTURY) {
553 				current = vrtc_get_current_time(vrtc);
554 				secs_to_rtc(current, vrtc);
555 
556 				if(offset == 0xCU) {
557 					pio_req->value = vrtc_get_reg_c(vrtc);
558 				} else {
559 					pio_req->value = *((uint8_t *)&vrtc->rtcdev + offset);
560 				}
561 				RTC_DEBUG("read 0x%x, 0x%x", offset, pio_req->value);
562 			} else {
563 				pr_err("vrtc read invalid addr 0x%x", offset);
564 				ret = false;
565 			}
566 		}
567 	}
568 
569 	return ret;
570 }
571 
vrtc_is_time_register(uint32_t offset)572 static inline bool vrtc_is_time_register(uint32_t offset)
573 {
574 	return ((offset == RTC_SEC) || (offset == RTC_MIN) || (offset == RTC_HRS) || (offset == RTC_DAY)
575 			|| (offset == RTC_MONTH) || (offset == RTC_YEAR) || (offset == RTC_CENTURY));
576 }
577 
578 /**
579  * @brief Write a value to the virtual RTC.
580  *
581  * This function writes a specified value to the virtual RTC at a given offset. To write to the virtual RTC, the guest
582  * writes the register index to the RTC address port and then writes the register value to the RTC data port. This
583  * function is used to simulate the behavior of writing in a virtualized environment.
584  *
585  * - If the accessed port is CMOS_ADDR_PORT and the width is 1 byte, it will store the value as the index and return.
586  * - If the accessed port is CMOS_DATA_PORT,
587  *   - For Service VM, it will directly write the value to the physical CMOS register. If the physical date/time is
588  *     changed, for RT VMs and pre-launched VMs, the RTC/TSC snapshots will be updated. Those snapshots are used to
589  *     emulate the virtual date/time for non-Service VM.
590  *   - For a non-Service VM, it will ignore the write to the RTC_STATUSA, RTC_INTR and RTC_STATUSD. Otherwise, it will
591  *     update the virtual register value and RTC time. And for Post-launched VM, it will send a VM event to notify the
592  *     VM of the change in the RTC time if the address port is in the range of the time registers.
593  *
594  * @param[inout] vcpu Pointer to the virtual CPU that is writing to the virtual RTC.
595  * @param[in] addr The address port to write to.
596  * @param[in] width Width of the value to be written to the virtual RTC.
597  * @param[in] value Value to be written to the virtual RTC.
598  *
599  * @return A boolean value indicating whether the write operation is handled successfully, which is always true in
600  *         current design. It either updates the physical registers, updates the virtual registers, or ignores the
601  *         write.
602  *
603  * @retval true The write operation is handled successfully.
604  *
605  * @pre vcpu != NULL
606  * @pre vcpu->vm != NULL
607  * @pre addr == 0x70U || addr == 0x71U
608  *
609  * @post N/A
610  *
611  * @remark N/A
612  */
vrtc_write(struct acrn_vcpu * vcpu,uint16_t addr,size_t width,uint32_t value)613 static bool vrtc_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t width,
614 			uint32_t value)
615 {
616 	time_t current, after;
617 	struct acrn_vrtc *vrtc = &vcpu->vm->vrtc;
618 	struct acrn_vrtc temp_vrtc;
619 	uint8_t mask = 0xFFU;
620 	struct vm_event rtc_chg_event;
621 	struct rtc_change_event_data *edata = (struct rtc_change_event_data *)rtc_chg_event.event_data;
622 
623 	if ((width == 1U) && (addr == CMOS_ADDR_PORT)) {
624 		vrtc->addr = (uint8_t)(value & 0x7FU);
625 	} else {
626 		if (is_service_vm(vcpu->vm)) {
627 			if (vrtc_is_time_register(vrtc->addr)) {
628 				current = vrtc_get_physical_rtc_time(&temp_vrtc);
629 				cmos_set_reg_val(vcpu->vm->vrtc.addr, (uint8_t)(value & 0xFFU));
630 				after = vrtc_get_physical_rtc_time(&temp_vrtc);
631 				vrtc_update_basetime(after, current - after);
632 			} else {
633 				cmos_set_reg_val(vcpu->vm->vrtc.addr, (uint8_t)(value & 0xFFU));
634 			}
635 		} else {
636 			switch (vrtc->addr) {
637 			case RTC_STATUSA:
638 			case RTC_INTR:
639 			case RTC_STATUSD:
640 				RTC_DEBUG("RTC reg_%x set to %#x (ignored)\n", vrtc->addr, value);
641 				break;
642 			case RTC_STATUSB:
643 				vrtc_set_reg_b(vrtc, value);
644 				RTC_DEBUG("RTC reg_b set to %#x\n", value);
645 				break;
646 			case RTC_SECALRM:
647 			case RTC_MINALRM:
648 				/* FALLTHRU */
649 			case RTC_HRSALRM:
650 				*((uint8_t *)&vrtc->rtcdev + vrtc->addr) = (uint8_t)(value & 0x7FU);
651 				RTC_DEBUG("RTC alarm reg(%d) set to %#x (ignored)\n", vrtc->addr, value);
652 				break;
653 			case RTC_SEC:
654 				/*
655 				 * High order bit of 'seconds' is readonly.
656 				 */
657 				mask = 0x7FU;
658 				/* FALLTHRU */
659 			default:
660 				RTC_DEBUG("RTC offset %#x set to %#x\n", vrtc->addr, value);
661 				*((uint8_t *)&vrtc->rtcdev + vrtc->addr) = (uint8_t)(value & mask);
662 				current = vrtc_get_current_time(vrtc);
663 				after = rtc_to_secs(vrtc);
664 				spinlock_obtain(&vrtc_rebase_lock);
665 				vrtc->offset_rtctime += after - current;
666 				vrtc->last_rtctime = VRTC_BROKEN_TIME;
667 				spinlock_release(&vrtc_rebase_lock);
668 				if (is_postlaunched_vm(vcpu->vm) && vrtc_is_time_register(vrtc->addr)) {
669 					rtc_chg_event.type = VM_EVENT_RTC_CHG;
670 					edata->delta_time = after - current;
671 					edata->last_time = current;
672 					send_vm_event(vcpu->vm, &rtc_chg_event);
673 				}
674 				break;
675 			}
676 		}
677 	}
678 
679 	return true;
680 }
681 
682 #define CALIBRATE_PERIOD	(3 * 3600 * 1000)	/* By ms, totally 3 hours. */
683 static struct hv_timer calibrate_timer;
684 
vrtc_get_physical_rtc_time(struct acrn_vrtc * vrtc)685 static time_t vrtc_get_physical_rtc_time(struct acrn_vrtc *vrtc)
686 {
687 	struct rtcdev *vrtcdev = &vrtc->rtcdev;
688 
689 	vrtcdev->sec = cmos_get_reg_val(RTC_SEC);
690 	vrtcdev->min = cmos_get_reg_val(RTC_MIN);
691 	vrtcdev->hour = cmos_get_reg_val(RTC_HRS);
692 	vrtcdev->day_of_month = cmos_get_reg_val(RTC_DAY);
693 	vrtcdev->month = cmos_get_reg_val(RTC_MONTH);
694 	vrtcdev->year = cmos_get_reg_val(RTC_YEAR);
695 	vrtcdev->century = cmos_get_reg_val(RTC_CENTURY);
696 	vrtcdev->reg_b = cmos_get_reg_val(RTC_STATUSB);
697 
698 	return rtc_to_secs(vrtc);
699 }
700 
vrtc_update_basetime(time_t physical_time,time_t offset)701 static void vrtc_update_basetime(time_t physical_time, time_t offset)
702 {
703 	struct acrn_vm *vm;
704 	uint32_t vm_id;
705 
706 	for (vm_id = 0U; vm_id < CONFIG_MAX_VM_NUM; vm_id++) {
707 		vm = get_vm_from_vmid(vm_id);
708 		if (is_rt_vm(vm) || is_prelaunched_vm(vm)) {
709 			spinlock_obtain(&vrtc_rebase_lock);
710 			vm->vrtc.base_tsc = cpu_ticks();
711 			vm->vrtc.base_rtctime = physical_time;
712 			vm->vrtc.offset_rtctime += offset;
713 			spinlock_release(&vrtc_rebase_lock);
714 		}
715 	}
716 }
717 
calibrate_timer_callback(__unused void * data)718 static void calibrate_timer_callback(__unused void *data)
719 {
720 	struct acrn_vrtc temp_vrtc;
721 	time_t physical_time = vrtc_get_physical_rtc_time(&temp_vrtc);
722 
723 	vrtc_update_basetime(physical_time, 0);
724 }
725 
calibrate_setup_timer(void)726 static void calibrate_setup_timer(void)
727 {
728 	uint64_t period_in_cycle, fire_tsc;
729 
730 	period_in_cycle = TICKS_PER_MS * CALIBRATE_PERIOD;
731 	fire_tsc = cpu_ticks() + period_in_cycle;
732 	initialize_timer(&calibrate_timer,
733 			calibrate_timer_callback, NULL,
734 			fire_tsc, period_in_cycle);
735 
736 	/* Start an periodic timer */
737 	if (add_timer(&calibrate_timer) != 0) {
738 		pr_err("Failed to add calibrate timer");
739 	}
740 }
741 
vrtc_set_basetime(struct acrn_vrtc * vrtc)742 static void vrtc_set_basetime(struct acrn_vrtc *vrtc)
743 {
744 	struct rtcdev *vrtcdev = &vrtc->rtcdev;
745 	time_t current;
746 
747 	/*
748 	 * Read base time from physical rtc.
749 	 */
750 	vrtcdev->sec = cmos_get_reg_val(RTC_SEC);
751 	vrtcdev->min = cmos_get_reg_val(RTC_MIN);
752 	vrtcdev->hour = cmos_get_reg_val(RTC_HRS);
753 	vrtcdev->day_of_month = cmos_get_reg_val(RTC_DAY);
754 	vrtcdev->month = cmos_get_reg_val(RTC_MONTH);
755 	vrtcdev->year = cmos_get_reg_val(RTC_YEAR);
756 	vrtcdev->century = cmos_get_reg_val(RTC_CENTURY);
757 	vrtcdev->reg_a = cmos_get_reg_val(RTC_STATUSA) & (~RTCSA_TUP);
758 	vrtcdev->reg_b = cmos_get_reg_val(RTC_STATUSB);
759 	vrtcdev->reg_c = cmos_get_reg_val(RTC_INTR);
760 	vrtcdev->reg_d = cmos_get_reg_val(RTC_STATUSD);
761 
762 	current = rtc_to_secs(vrtc);
763 	spinlock_obtain(&vrtc_rebase_lock);
764 	vrtc->base_rtctime = current;
765 	vrtc->last_rtctime = VRTC_BROKEN_TIME;
766 	spinlock_release(&vrtc_rebase_lock);
767 }
768 
suspend_vrtc(void)769 void suspend_vrtc(void)
770 {
771 	/* For service vm */
772 	del_timer(&calibrate_timer);
773 }
774 
resume_vrtc(void)775 void resume_vrtc(void)
776 {
777 	/* For service vm */
778 	calibrate_setup_timer();
779 }
780 
781 /**
782  * @brief Initialize the virtual RTC.
783  *
784  * This function initializes the virtual RTC (Real-Time Clock) device for the given virtual machine. It sets up the
785  * necessary data structures and state required for the RTC to function correctly. This function should be called during
786  * the initialization phase of the virtual machine.
787  *
788  * - When Service VM's vRTC device is initialized, a periodic timer (every 3 hours) is set up to calibrate the virtual
789  *   date/time of other VMs. When the calibration timer is triggered, for RT VMs and pre-launched VMs, the TSC/RTC
790  *   snapshots are updated to reflect the physical TSC/RTC-time at that moment.
791  * - When non-Service VM's vRTC device is initialized, the TSC/RTC snapshots are initialized to reflect the physical
792  *   TSC/RTC-time at the moment.
793  *
794  * @param[inout] vm The virtual machine that contains the virtual RTC to be initialized.
795  *
796  * @return None
797  *
798  * @pre vm != NULL
799  *
800  * @post N/A
801  *
802  * @remark N/A
803  */
vrtc_init(struct acrn_vm * vm)804 void vrtc_init(struct acrn_vm *vm)
805 {
806 	struct vm_io_range range = {
807 	.base = CMOS_ADDR_PORT, .len = 2U};
808 
809 	/* Initializing the CMOS RAM offset to 0U */
810 	vm->vrtc.addr = 0U;
811 
812 	vm->vrtc.vm = vm;
813 	register_pio_emulation_handler(vm, RTC_PIO_IDX, &range, vrtc_read, vrtc_write);
814 
815 	if (is_service_vm(vm)) {
816 		calibrate_setup_timer();
817 	} else {
818 		vrtc_set_basetime(&vm->vrtc);
819 		vm->vrtc.base_tsc = cpu_ticks();
820 	}
821 }
822 
823 /**
824  * @}
825  */