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, ¢ury) < 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 */