Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/amd64/vmm/io/vrtc.c
39537 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2014, Neel Natu ([email protected])
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice unmodified, this list of conditions, and the following
12
* disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
*/
28
29
#include <sys/cdefs.h>
30
#include "opt_bhyve_snapshot.h"
31
32
#include <sys/param.h>
33
#include <sys/systm.h>
34
#include <sys/queue.h>
35
#include <sys/kernel.h>
36
#include <sys/malloc.h>
37
#include <sys/lock.h>
38
#include <sys/mutex.h>
39
#include <sys/clock.h>
40
#include <sys/sysctl.h>
41
42
#include <machine/vmm.h>
43
#include <machine/vmm_snapshot.h>
44
45
#include <isa/rtc.h>
46
47
#include <dev/vmm/vmm_ktr.h>
48
49
#include "vatpic.h"
50
#include "vioapic.h"
51
#include "vrtc.h"
52
53
/* Register layout of the RTC */
54
struct rtcdev {
55
uint8_t sec;
56
uint8_t alarm_sec;
57
uint8_t min;
58
uint8_t alarm_min;
59
uint8_t hour;
60
uint8_t alarm_hour;
61
uint8_t day_of_week;
62
uint8_t day_of_month;
63
uint8_t month;
64
uint8_t year;
65
uint8_t reg_a;
66
uint8_t reg_b;
67
uint8_t reg_c;
68
uint8_t reg_d;
69
uint8_t nvram[36];
70
uint8_t century;
71
uint8_t nvram2[128 - 51];
72
} __packed;
73
CTASSERT(sizeof(struct rtcdev) == 128);
74
CTASSERT(offsetof(struct rtcdev, century) == RTC_CENTURY);
75
76
struct vrtc {
77
struct vm *vm;
78
struct mtx mtx;
79
struct callout callout;
80
u_int addr; /* RTC register to read or write */
81
sbintime_t base_uptime;
82
time_t base_rtctime;
83
struct rtcdev rtcdev;
84
};
85
86
#define VRTC_LOCK(vrtc) mtx_lock(&((vrtc)->mtx))
87
#define VRTC_UNLOCK(vrtc) mtx_unlock(&((vrtc)->mtx))
88
#define VRTC_LOCKED(vrtc) mtx_owned(&((vrtc)->mtx))
89
90
/*
91
* RTC time is considered "broken" if:
92
* - RTC updates are halted by the guest
93
* - RTC date/time fields have invalid values
94
*/
95
#define VRTC_BROKEN_TIME ((time_t)-1)
96
97
#define RTC_IRQ 8
98
#define RTCSB_BIN 0x04
99
#define RTCSB_ALL_INTRS (RTCSB_UINTR | RTCSB_AINTR | RTCSB_PINTR)
100
#define rtc_halted(vrtc) ((vrtc->rtcdev.reg_b & RTCSB_HALT) != 0)
101
#define aintr_enabled(vrtc) (((vrtc)->rtcdev.reg_b & RTCSB_AINTR) != 0)
102
#define pintr_enabled(vrtc) (((vrtc)->rtcdev.reg_b & RTCSB_PINTR) != 0)
103
#define uintr_enabled(vrtc) (((vrtc)->rtcdev.reg_b & RTCSB_UINTR) != 0)
104
105
static void vrtc_callout_handler(void *arg);
106
static void vrtc_set_reg_c(struct vrtc *vrtc, uint8_t newval);
107
108
static MALLOC_DEFINE(M_VRTC, "vrtc", "bhyve virtual rtc");
109
110
SYSCTL_DECL(_hw_vmm);
111
SYSCTL_NODE(_hw_vmm, OID_AUTO, vrtc, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL,
112
NULL);
113
114
static int rtc_flag_broken_time = 1;
115
SYSCTL_INT(_hw_vmm_vrtc, OID_AUTO, flag_broken_time, CTLFLAG_RDTUN,
116
&rtc_flag_broken_time, 0, "Stop guest when invalid RTC time is detected");
117
118
static __inline bool
119
divider_enabled(int reg_a)
120
{
121
/*
122
* The RTC is counting only when dividers are not held in reset.
123
*/
124
return ((reg_a & 0x70) == 0x20);
125
}
126
127
static __inline bool
128
update_enabled(struct vrtc *vrtc)
129
{
130
/*
131
* RTC date/time can be updated only if:
132
* - divider is not held in reset
133
* - guest has not disabled updates
134
* - the date/time fields have valid contents
135
*/
136
if (!divider_enabled(vrtc->rtcdev.reg_a))
137
return (false);
138
139
if (rtc_halted(vrtc))
140
return (false);
141
142
if (vrtc->base_rtctime == VRTC_BROKEN_TIME)
143
return (false);
144
145
return (true);
146
}
147
148
static time_t
149
vrtc_curtime(struct vrtc *vrtc, sbintime_t *basetime)
150
{
151
sbintime_t now, delta;
152
time_t t, secs;
153
154
KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
155
156
t = vrtc->base_rtctime;
157
*basetime = vrtc->base_uptime;
158
if (update_enabled(vrtc)) {
159
now = sbinuptime();
160
delta = now - vrtc->base_uptime;
161
KASSERT(delta >= 0, ("vrtc_curtime: uptime went backwards: "
162
"%#lx to %#lx", vrtc->base_uptime, now));
163
secs = delta / SBT_1S;
164
t += secs;
165
*basetime += secs * SBT_1S;
166
}
167
return (t);
168
}
169
170
static __inline uint8_t
171
rtcset(struct rtcdev *rtc, int val)
172
{
173
174
KASSERT(val >= 0 && val < 100, ("%s: invalid bin2bcd index %d",
175
__func__, val));
176
177
return ((rtc->reg_b & RTCSB_BIN) ? val : bin2bcd_data[val]);
178
}
179
180
static void
181
secs_to_rtc(time_t rtctime, struct vrtc *vrtc, int force_update)
182
{
183
struct clocktime ct;
184
struct timespec ts;
185
struct rtcdev *rtc;
186
int hour;
187
188
KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
189
190
if (rtctime < 0) {
191
KASSERT(rtctime == VRTC_BROKEN_TIME,
192
("%s: invalid vrtc time %#lx", __func__, rtctime));
193
return;
194
}
195
196
/*
197
* If the RTC is halted then the guest has "ownership" of the
198
* date/time fields. Don't update the RTC date/time fields in
199
* this case (unless forced).
200
*/
201
if (rtc_halted(vrtc) && !force_update)
202
return;
203
204
ts.tv_sec = rtctime;
205
ts.tv_nsec = 0;
206
clock_ts_to_ct(&ts, &ct);
207
208
KASSERT(ct.sec >= 0 && ct.sec <= 59, ("invalid clocktime sec %d",
209
ct.sec));
210
KASSERT(ct.min >= 0 && ct.min <= 59, ("invalid clocktime min %d",
211
ct.min));
212
KASSERT(ct.hour >= 0 && ct.hour <= 23, ("invalid clocktime hour %d",
213
ct.hour));
214
KASSERT(ct.dow >= 0 && ct.dow <= 6, ("invalid clocktime wday %d",
215
ct.dow));
216
KASSERT(ct.day >= 1 && ct.day <= 31, ("invalid clocktime mday %d",
217
ct.day));
218
KASSERT(ct.mon >= 1 && ct.mon <= 12, ("invalid clocktime month %d",
219
ct.mon));
220
KASSERT(ct.year >= POSIX_BASE_YEAR, ("invalid clocktime year %d",
221
ct.year));
222
223
rtc = &vrtc->rtcdev;
224
rtc->sec = rtcset(rtc, ct.sec);
225
rtc->min = rtcset(rtc, ct.min);
226
227
if (rtc->reg_b & RTCSB_24HR) {
228
hour = ct.hour;
229
} else {
230
/*
231
* Convert to the 12-hour format.
232
*/
233
switch (ct.hour) {
234
case 0: /* 12 AM */
235
case 12: /* 12 PM */
236
hour = 12;
237
break;
238
default:
239
/*
240
* The remaining 'ct.hour' values are interpreted as:
241
* [1 - 11] -> 1 - 11 AM
242
* [13 - 23] -> 1 - 11 PM
243
*/
244
hour = ct.hour % 12;
245
break;
246
}
247
}
248
249
rtc->hour = rtcset(rtc, hour);
250
251
if ((rtc->reg_b & RTCSB_24HR) == 0 && ct.hour >= 12)
252
rtc->hour |= 0x80; /* set MSB to indicate PM */
253
254
rtc->day_of_week = rtcset(rtc, ct.dow + 1);
255
rtc->day_of_month = rtcset(rtc, ct.day);
256
rtc->month = rtcset(rtc, ct.mon);
257
rtc->year = rtcset(rtc, ct.year % 100);
258
rtc->century = rtcset(rtc, ct.year / 100);
259
}
260
261
static int
262
rtcget(struct rtcdev *rtc, int val, int *retval)
263
{
264
uint8_t upper, lower;
265
266
if (rtc->reg_b & RTCSB_BIN) {
267
*retval = val;
268
return (0);
269
}
270
271
lower = val & 0xf;
272
upper = (val >> 4) & 0xf;
273
274
if (lower > 9 || upper > 9)
275
return (-1);
276
277
*retval = upper * 10 + lower;
278
return (0);
279
}
280
281
static time_t
282
rtc_to_secs(struct vrtc *vrtc)
283
{
284
struct clocktime ct;
285
struct timespec ts;
286
struct rtcdev *rtc;
287
#ifdef KTR
288
struct vm *vm = vrtc->vm;
289
#endif
290
int century, error, hour, pm, year;
291
292
KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
293
294
rtc = &vrtc->rtcdev;
295
296
bzero(&ct, sizeof(struct clocktime));
297
298
error = rtcget(rtc, rtc->sec, &ct.sec);
299
if (error || ct.sec < 0 || ct.sec > 59) {
300
VM_CTR2(vm, "Invalid RTC sec %#x/%d", rtc->sec, ct.sec);
301
goto fail;
302
}
303
304
error = rtcget(rtc, rtc->min, &ct.min);
305
if (error || ct.min < 0 || ct.min > 59) {
306
VM_CTR2(vm, "Invalid RTC min %#x/%d", rtc->min, ct.min);
307
goto fail;
308
}
309
310
pm = 0;
311
hour = rtc->hour;
312
if ((rtc->reg_b & RTCSB_24HR) == 0) {
313
if (hour & 0x80) {
314
hour &= ~0x80;
315
pm = 1;
316
}
317
}
318
error = rtcget(rtc, hour, &ct.hour);
319
if ((rtc->reg_b & RTCSB_24HR) == 0) {
320
if (ct.hour >= 1 && ct.hour <= 12) {
321
/*
322
* Convert from 12-hour format to internal 24-hour
323
* representation as follows:
324
*
325
* 12-hour format ct.hour
326
* 12 AM 0
327
* 1 - 11 AM 1 - 11
328
* 12 PM 12
329
* 1 - 11 PM 13 - 23
330
*/
331
if (ct.hour == 12)
332
ct.hour = 0;
333
if (pm)
334
ct.hour += 12;
335
} else {
336
VM_CTR2(vm, "Invalid RTC 12-hour format %#x/%d",
337
rtc->hour, ct.hour);
338
goto fail;
339
}
340
}
341
342
if (error || ct.hour < 0 || ct.hour > 23) {
343
VM_CTR2(vm, "Invalid RTC hour %#x/%d", rtc->hour, ct.hour);
344
goto fail;
345
}
346
347
/*
348
* Ignore 'rtc->dow' because some guests like Linux don't bother
349
* setting it at all while others like OpenBSD/i386 set it incorrectly.
350
*
351
* clock_ct_to_ts() does not depend on 'ct.dow' anyways so ignore it.
352
*/
353
ct.dow = -1;
354
355
error = rtcget(rtc, rtc->day_of_month, &ct.day);
356
if (error || ct.day < 1 || ct.day > 31) {
357
VM_CTR2(vm, "Invalid RTC mday %#x/%d", rtc->day_of_month,
358
ct.day);
359
goto fail;
360
}
361
362
error = rtcget(rtc, rtc->month, &ct.mon);
363
if (error || ct.mon < 1 || ct.mon > 12) {
364
VM_CTR2(vm, "Invalid RTC month %#x/%d", rtc->month, ct.mon);
365
goto fail;
366
}
367
368
error = rtcget(rtc, rtc->year, &year);
369
if (error || year < 0 || year > 99) {
370
VM_CTR2(vm, "Invalid RTC year %#x/%d", rtc->year, year);
371
goto fail;
372
}
373
374
error = rtcget(rtc, rtc->century, &century);
375
ct.year = century * 100 + year;
376
if (error || ct.year < POSIX_BASE_YEAR) {
377
VM_CTR2(vm, "Invalid RTC century %#x/%d", rtc->century,
378
ct.year);
379
goto fail;
380
}
381
382
error = clock_ct_to_ts(&ct, &ts);
383
if (error || ts.tv_sec < 0) {
384
VM_CTR3(vm, "Invalid RTC clocktime.date %04d-%02d-%02d",
385
ct.year, ct.mon, ct.day);
386
VM_CTR3(vm, "Invalid RTC clocktime.time %02d:%02d:%02d",
387
ct.hour, ct.min, ct.sec);
388
goto fail;
389
}
390
return (ts.tv_sec); /* success */
391
fail:
392
/*
393
* Stop updating the RTC if the date/time fields programmed by
394
* the guest are invalid.
395
*/
396
VM_CTR0(vrtc->vm, "Invalid RTC date/time programming detected");
397
return (VRTC_BROKEN_TIME);
398
}
399
400
static int
401
vrtc_time_update(struct vrtc *vrtc, time_t newtime, sbintime_t newbase)
402
{
403
struct rtcdev *rtc;
404
time_t oldtime;
405
uint8_t alarm_sec, alarm_min, alarm_hour;
406
407
KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
408
409
rtc = &vrtc->rtcdev;
410
alarm_sec = rtc->alarm_sec;
411
alarm_min = rtc->alarm_min;
412
alarm_hour = rtc->alarm_hour;
413
414
oldtime = vrtc->base_rtctime;
415
VM_CTR2(vrtc->vm, "Updating RTC secs from %#lx to %#lx",
416
oldtime, newtime);
417
418
VM_CTR2(vrtc->vm, "Updating RTC base uptime from %#lx to %#lx",
419
vrtc->base_uptime, newbase);
420
vrtc->base_uptime = newbase;
421
422
if (newtime == oldtime)
423
return (0);
424
425
/*
426
* If 'newtime' indicates that RTC updates are disabled then just
427
* record that and return. There is no need to do alarm interrupt
428
* processing in this case.
429
*/
430
if (newtime == VRTC_BROKEN_TIME) {
431
vrtc->base_rtctime = VRTC_BROKEN_TIME;
432
return (0);
433
}
434
435
/*
436
* Return an error if RTC updates are halted by the guest.
437
*/
438
if (rtc_halted(vrtc)) {
439
VM_CTR0(vrtc->vm, "RTC update halted by guest");
440
return (EBUSY);
441
}
442
443
do {
444
/*
445
* If the alarm interrupt is enabled and 'oldtime' is valid
446
* then visit all the seconds between 'oldtime' and 'newtime'
447
* to check for the alarm condition.
448
*
449
* Otherwise move the RTC time forward directly to 'newtime'.
450
*/
451
if (aintr_enabled(vrtc) && oldtime != VRTC_BROKEN_TIME)
452
vrtc->base_rtctime++;
453
else
454
vrtc->base_rtctime = newtime;
455
456
if (aintr_enabled(vrtc)) {
457
/*
458
* Update the RTC date/time fields before checking
459
* if the alarm conditions are satisfied.
460
*/
461
secs_to_rtc(vrtc->base_rtctime, vrtc, 0);
462
463
if ((alarm_sec >= 0xC0 || alarm_sec == rtc->sec) &&
464
(alarm_min >= 0xC0 || alarm_min == rtc->min) &&
465
(alarm_hour >= 0xC0 || alarm_hour == rtc->hour)) {
466
vrtc_set_reg_c(vrtc, rtc->reg_c | RTCIR_ALARM);
467
}
468
}
469
} while (vrtc->base_rtctime != newtime);
470
471
if (uintr_enabled(vrtc))
472
vrtc_set_reg_c(vrtc, rtc->reg_c | RTCIR_UPDATE);
473
474
return (0);
475
}
476
477
static sbintime_t
478
vrtc_freq(struct vrtc *vrtc)
479
{
480
int ratesel;
481
482
static sbintime_t pf[16] = {
483
0,
484
SBT_1S / 256,
485
SBT_1S / 128,
486
SBT_1S / 8192,
487
SBT_1S / 4096,
488
SBT_1S / 2048,
489
SBT_1S / 1024,
490
SBT_1S / 512,
491
SBT_1S / 256,
492
SBT_1S / 128,
493
SBT_1S / 64,
494
SBT_1S / 32,
495
SBT_1S / 16,
496
SBT_1S / 8,
497
SBT_1S / 4,
498
SBT_1S / 2,
499
};
500
501
KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
502
503
/*
504
* If both periodic and alarm interrupts are enabled then use the
505
* periodic frequency to drive the callout. The minimum periodic
506
* frequency (2 Hz) is higher than the alarm frequency (1 Hz) so
507
* piggyback the alarm on top of it. The same argument applies to
508
* the update interrupt.
509
*/
510
if (pintr_enabled(vrtc) && divider_enabled(vrtc->rtcdev.reg_a)) {
511
ratesel = vrtc->rtcdev.reg_a & 0xf;
512
return (pf[ratesel]);
513
} else if (aintr_enabled(vrtc) && update_enabled(vrtc)) {
514
return (SBT_1S);
515
} else if (uintr_enabled(vrtc) && update_enabled(vrtc)) {
516
return (SBT_1S);
517
} else {
518
return (0);
519
}
520
}
521
522
static void
523
vrtc_callout_reset(struct vrtc *vrtc, sbintime_t freqsbt)
524
{
525
526
KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
527
528
if (freqsbt == 0) {
529
if (callout_active(&vrtc->callout)) {
530
VM_CTR0(vrtc->vm, "RTC callout stopped");
531
callout_stop(&vrtc->callout);
532
}
533
return;
534
}
535
VM_CTR1(vrtc->vm, "RTC callout frequency %d hz", SBT_1S / freqsbt);
536
callout_reset_sbt(&vrtc->callout, freqsbt, 0, vrtc_callout_handler,
537
vrtc, 0);
538
}
539
540
static void
541
vrtc_callout_handler(void *arg)
542
{
543
struct vrtc *vrtc = arg;
544
sbintime_t freqsbt, basetime;
545
time_t rtctime;
546
int error __diagused;
547
548
VM_CTR0(vrtc->vm, "vrtc callout fired");
549
550
VRTC_LOCK(vrtc);
551
if (callout_pending(&vrtc->callout)) /* callout was reset */
552
goto done;
553
554
if (!callout_active(&vrtc->callout)) /* callout was stopped */
555
goto done;
556
557
callout_deactivate(&vrtc->callout);
558
559
KASSERT((vrtc->rtcdev.reg_b & RTCSB_ALL_INTRS) != 0,
560
("gratuitous vrtc callout"));
561
562
if (pintr_enabled(vrtc))
563
vrtc_set_reg_c(vrtc, vrtc->rtcdev.reg_c | RTCIR_PERIOD);
564
565
if (aintr_enabled(vrtc) || uintr_enabled(vrtc)) {
566
rtctime = vrtc_curtime(vrtc, &basetime);
567
error = vrtc_time_update(vrtc, rtctime, basetime);
568
KASSERT(error == 0, ("%s: vrtc_time_update error %d",
569
__func__, error));
570
}
571
572
freqsbt = vrtc_freq(vrtc);
573
KASSERT(freqsbt != 0, ("%s: vrtc frequency cannot be zero", __func__));
574
vrtc_callout_reset(vrtc, freqsbt);
575
done:
576
VRTC_UNLOCK(vrtc);
577
}
578
579
static __inline void
580
vrtc_callout_check(struct vrtc *vrtc, sbintime_t freq)
581
{
582
int active __diagused;
583
584
active = callout_active(&vrtc->callout) ? 1 : 0;
585
KASSERT((freq == 0 && !active) || (freq != 0 && active),
586
("vrtc callout %s with frequency %#lx",
587
active ? "active" : "inactive", freq));
588
}
589
590
static void
591
vrtc_set_reg_c(struct vrtc *vrtc, uint8_t newval)
592
{
593
struct rtcdev *rtc;
594
int oldirqf, newirqf;
595
uint8_t oldval, changed;
596
597
KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
598
599
rtc = &vrtc->rtcdev;
600
newval &= RTCIR_ALARM | RTCIR_PERIOD | RTCIR_UPDATE;
601
602
oldirqf = rtc->reg_c & RTCIR_INT;
603
if ((aintr_enabled(vrtc) && (newval & RTCIR_ALARM) != 0) ||
604
(pintr_enabled(vrtc) && (newval & RTCIR_PERIOD) != 0) ||
605
(uintr_enabled(vrtc) && (newval & RTCIR_UPDATE) != 0)) {
606
newirqf = RTCIR_INT;
607
} else {
608
newirqf = 0;
609
}
610
611
oldval = rtc->reg_c;
612
rtc->reg_c = newirqf | newval;
613
changed = oldval ^ rtc->reg_c;
614
if (changed) {
615
VM_CTR2(vrtc->vm, "RTC reg_c changed from %#x to %#x",
616
oldval, rtc->reg_c);
617
}
618
619
if (!oldirqf && newirqf) {
620
VM_CTR1(vrtc->vm, "RTC irq %d asserted", RTC_IRQ);
621
vatpic_pulse_irq(vrtc->vm, RTC_IRQ);
622
vioapic_pulse_irq(vrtc->vm, RTC_IRQ);
623
} else if (oldirqf && !newirqf) {
624
VM_CTR1(vrtc->vm, "RTC irq %d deasserted", RTC_IRQ);
625
}
626
}
627
628
static int
629
vrtc_set_reg_b(struct vrtc *vrtc, uint8_t newval)
630
{
631
struct rtcdev *rtc;
632
sbintime_t oldfreq, newfreq, basetime;
633
time_t curtime, rtctime;
634
int error __diagused;
635
uint8_t oldval, changed;
636
637
KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
638
639
rtc = &vrtc->rtcdev;
640
oldval = rtc->reg_b;
641
oldfreq = vrtc_freq(vrtc);
642
643
rtc->reg_b = newval;
644
changed = oldval ^ newval;
645
if (changed) {
646
VM_CTR2(vrtc->vm, "RTC reg_b changed from %#x to %#x",
647
oldval, newval);
648
}
649
650
if (changed & RTCSB_HALT) {
651
if ((newval & RTCSB_HALT) == 0) {
652
rtctime = rtc_to_secs(vrtc);
653
basetime = sbinuptime();
654
if (rtctime == VRTC_BROKEN_TIME) {
655
if (rtc_flag_broken_time)
656
return (-1);
657
}
658
} else {
659
curtime = vrtc_curtime(vrtc, &basetime);
660
KASSERT(curtime == vrtc->base_rtctime, ("%s: mismatch "
661
"between vrtc basetime (%#lx) and curtime (%#lx)",
662
__func__, vrtc->base_rtctime, curtime));
663
664
/*
665
* Force a refresh of the RTC date/time fields so
666
* they reflect the time right before the guest set
667
* the HALT bit.
668
*/
669
secs_to_rtc(curtime, vrtc, 1);
670
671
/*
672
* Updates are halted so mark 'base_rtctime' to denote
673
* that the RTC date/time is in flux.
674
*/
675
rtctime = VRTC_BROKEN_TIME;
676
rtc->reg_b &= ~RTCSB_UINTR;
677
}
678
error = vrtc_time_update(vrtc, rtctime, basetime);
679
KASSERT(error == 0, ("vrtc_time_update error %d", error));
680
}
681
682
/*
683
* Side effect of changes to the interrupt enable bits.
684
*/
685
if (changed & RTCSB_ALL_INTRS)
686
vrtc_set_reg_c(vrtc, vrtc->rtcdev.reg_c);
687
688
/*
689
* Change the callout frequency if it has changed.
690
*/
691
newfreq = vrtc_freq(vrtc);
692
if (newfreq != oldfreq)
693
vrtc_callout_reset(vrtc, newfreq);
694
else
695
vrtc_callout_check(vrtc, newfreq);
696
697
/*
698
* The side effect of bits that control the RTC date/time format
699
* is handled lazily when those fields are actually read.
700
*/
701
return (0);
702
}
703
704
static void
705
vrtc_set_reg_a(struct vrtc *vrtc, uint8_t newval)
706
{
707
sbintime_t oldfreq, newfreq;
708
uint8_t oldval, changed;
709
710
KASSERT(VRTC_LOCKED(vrtc), ("%s: vrtc not locked", __func__));
711
712
newval &= ~RTCSA_TUP;
713
oldval = vrtc->rtcdev.reg_a;
714
oldfreq = vrtc_freq(vrtc);
715
716
if (divider_enabled(oldval) && !divider_enabled(newval)) {
717
VM_CTR2(vrtc->vm, "RTC divider held in reset at %#lx/%#lx",
718
vrtc->base_rtctime, vrtc->base_uptime);
719
} else if (!divider_enabled(oldval) && divider_enabled(newval)) {
720
/*
721
* If the dividers are coming out of reset then update
722
* 'base_uptime' before this happens. This is done to
723
* maintain the illusion that the RTC date/time was frozen
724
* while the dividers were disabled.
725
*/
726
vrtc->base_uptime = sbinuptime();
727
VM_CTR2(vrtc->vm, "RTC divider out of reset at %#lx/%#lx",
728
vrtc->base_rtctime, vrtc->base_uptime);
729
} else {
730
/* NOTHING */
731
}
732
733
vrtc->rtcdev.reg_a = newval;
734
changed = oldval ^ newval;
735
if (changed) {
736
VM_CTR2(vrtc->vm, "RTC reg_a changed from %#x to %#x",
737
oldval, newval);
738
}
739
740
/*
741
* Side effect of changes to rate select and divider enable bits.
742
*/
743
newfreq = vrtc_freq(vrtc);
744
if (newfreq != oldfreq)
745
vrtc_callout_reset(vrtc, newfreq);
746
else
747
vrtc_callout_check(vrtc, newfreq);
748
}
749
750
int
751
vrtc_set_time(struct vm *vm, time_t secs)
752
{
753
struct vrtc *vrtc;
754
int error;
755
756
vrtc = vm_rtc(vm);
757
VRTC_LOCK(vrtc);
758
error = vrtc_time_update(vrtc, secs, sbinuptime());
759
VRTC_UNLOCK(vrtc);
760
761
if (error) {
762
VM_CTR2(vrtc->vm, "Error %d setting RTC time to %#lx", error,
763
secs);
764
} else {
765
VM_CTR1(vrtc->vm, "RTC time set to %#lx", secs);
766
}
767
768
return (error);
769
}
770
771
time_t
772
vrtc_get_time(struct vm *vm)
773
{
774
struct vrtc *vrtc;
775
sbintime_t basetime;
776
time_t t;
777
778
vrtc = vm_rtc(vm);
779
VRTC_LOCK(vrtc);
780
t = vrtc_curtime(vrtc, &basetime);
781
VRTC_UNLOCK(vrtc);
782
783
return (t);
784
}
785
786
int
787
vrtc_nvram_write(struct vm *vm, int offset, uint8_t value)
788
{
789
struct vrtc *vrtc;
790
uint8_t *ptr;
791
792
vrtc = vm_rtc(vm);
793
794
/*
795
* Don't allow writes to RTC control registers or the date/time fields.
796
*/
797
if (offset < offsetof(struct rtcdev, nvram[0]) ||
798
offset == RTC_CENTURY || offset >= sizeof(struct rtcdev)) {
799
VM_CTR1(vrtc->vm, "RTC nvram write to invalid offset %d",
800
offset);
801
return (EINVAL);
802
}
803
804
VRTC_LOCK(vrtc);
805
ptr = (uint8_t *)(&vrtc->rtcdev);
806
ptr[offset] = value;
807
VM_CTR2(vrtc->vm, "RTC nvram write %#x to offset %#x", value, offset);
808
VRTC_UNLOCK(vrtc);
809
810
return (0);
811
}
812
813
int
814
vrtc_nvram_read(struct vm *vm, int offset, uint8_t *retval)
815
{
816
struct vrtc *vrtc;
817
sbintime_t basetime;
818
time_t curtime;
819
uint8_t *ptr;
820
821
/*
822
* Allow all offsets in the RTC to be read.
823
*/
824
if (offset < 0 || offset >= sizeof(struct rtcdev))
825
return (EINVAL);
826
827
vrtc = vm_rtc(vm);
828
VRTC_LOCK(vrtc);
829
830
/*
831
* Update RTC date/time fields if necessary.
832
*/
833
if (offset < 10 || offset == RTC_CENTURY) {
834
curtime = vrtc_curtime(vrtc, &basetime);
835
secs_to_rtc(curtime, vrtc, 0);
836
}
837
838
ptr = (uint8_t *)(&vrtc->rtcdev);
839
*retval = ptr[offset];
840
841
VRTC_UNLOCK(vrtc);
842
return (0);
843
}
844
845
int
846
vrtc_addr_handler(struct vm *vm, bool in, int port, int bytes, uint32_t *val)
847
{
848
struct vrtc *vrtc;
849
850
vrtc = vm_rtc(vm);
851
852
if (bytes != 1)
853
return (-1);
854
855
if (in) {
856
*val = 0xff;
857
return (0);
858
}
859
860
VRTC_LOCK(vrtc);
861
vrtc->addr = *val & 0x7f;
862
VRTC_UNLOCK(vrtc);
863
864
return (0);
865
}
866
867
int
868
vrtc_data_handler(struct vm *vm, bool in, int port, int bytes, uint32_t *val)
869
{
870
struct vrtc *vrtc;
871
struct rtcdev *rtc;
872
sbintime_t basetime;
873
time_t curtime;
874
int error, offset;
875
876
vrtc = vm_rtc(vm);
877
rtc = &vrtc->rtcdev;
878
879
if (bytes != 1)
880
return (-1);
881
882
VRTC_LOCK(vrtc);
883
offset = vrtc->addr;
884
if (offset >= sizeof(struct rtcdev)) {
885
VRTC_UNLOCK(vrtc);
886
return (-1);
887
}
888
889
error = 0;
890
curtime = vrtc_curtime(vrtc, &basetime);
891
vrtc_time_update(vrtc, curtime, basetime);
892
893
/*
894
* Update RTC date/time fields if necessary.
895
*
896
* This is not just for reads of the RTC. The side-effect of writing
897
* the century byte requires other RTC date/time fields (e.g. sec)
898
* to be updated here.
899
*/
900
if (offset < 10 || offset == RTC_CENTURY)
901
secs_to_rtc(curtime, vrtc, 0);
902
903
if (in) {
904
if (offset == 12) {
905
/*
906
* XXX
907
* reg_c interrupt flags are updated only if the
908
* corresponding interrupt enable bit in reg_b is set.
909
*/
910
*val = vrtc->rtcdev.reg_c;
911
vrtc_set_reg_c(vrtc, 0);
912
} else {
913
*val = *((uint8_t *)rtc + offset);
914
}
915
VM_CTR2(vm, "Read value %#x from RTC offset %#x",
916
*val, offset);
917
} else {
918
switch (offset) {
919
case 10:
920
VM_CTR1(vm, "RTC reg_a set to %#x", *val);
921
vrtc_set_reg_a(vrtc, *val);
922
break;
923
case 11:
924
VM_CTR1(vm, "RTC reg_b set to %#x", *val);
925
error = vrtc_set_reg_b(vrtc, *val);
926
break;
927
case 12:
928
VM_CTR1(vm, "RTC reg_c set to %#x (ignored)",
929
*val);
930
break;
931
case 13:
932
VM_CTR1(vm, "RTC reg_d set to %#x (ignored)",
933
*val);
934
break;
935
case 0:
936
/*
937
* High order bit of 'seconds' is readonly.
938
*/
939
*val &= 0x7f;
940
/* FALLTHRU */
941
default:
942
VM_CTR2(vm, "RTC offset %#x set to %#x",
943
offset, *val);
944
*((uint8_t *)rtc + offset) = *val;
945
break;
946
}
947
948
/*
949
* XXX some guests (e.g. OpenBSD) write the century byte
950
* outside of RTCSB_HALT so re-calculate the RTC date/time.
951
*/
952
if (offset == RTC_CENTURY && !rtc_halted(vrtc)) {
953
curtime = rtc_to_secs(vrtc);
954
error = vrtc_time_update(vrtc, curtime, sbinuptime());
955
KASSERT(!error, ("vrtc_time_update error %d", error));
956
if (curtime == VRTC_BROKEN_TIME && rtc_flag_broken_time)
957
error = -1;
958
}
959
}
960
VRTC_UNLOCK(vrtc);
961
return (error);
962
}
963
964
void
965
vrtc_reset(struct vrtc *vrtc)
966
{
967
struct rtcdev *rtc;
968
969
VRTC_LOCK(vrtc);
970
971
rtc = &vrtc->rtcdev;
972
vrtc_set_reg_b(vrtc, rtc->reg_b & ~(RTCSB_ALL_INTRS | RTCSB_SQWE));
973
vrtc_set_reg_c(vrtc, 0);
974
KASSERT(!callout_active(&vrtc->callout), ("rtc callout still active"));
975
976
VRTC_UNLOCK(vrtc);
977
}
978
979
struct vrtc *
980
vrtc_init(struct vm *vm)
981
{
982
struct vrtc *vrtc;
983
struct rtcdev *rtc;
984
time_t curtime;
985
986
vrtc = malloc(sizeof(struct vrtc), M_VRTC, M_WAITOK | M_ZERO);
987
vrtc->vm = vm;
988
mtx_init(&vrtc->mtx, "vrtc lock", NULL, MTX_DEF);
989
callout_init(&vrtc->callout, 1);
990
991
/* Allow dividers to keep time but disable everything else */
992
rtc = &vrtc->rtcdev;
993
rtc->reg_a = 0x20;
994
rtc->reg_b = RTCSB_24HR;
995
rtc->reg_c = 0;
996
rtc->reg_d = RTCSD_PWR;
997
998
/* Reset the index register to a safe value. */
999
vrtc->addr = RTC_STATUSD;
1000
1001
/*
1002
* Initialize RTC time to 00:00:00 Jan 1, 1970.
1003
*/
1004
curtime = 0;
1005
1006
VRTC_LOCK(vrtc);
1007
vrtc->base_rtctime = VRTC_BROKEN_TIME;
1008
vrtc_time_update(vrtc, curtime, sbinuptime());
1009
secs_to_rtc(curtime, vrtc, 0);
1010
VRTC_UNLOCK(vrtc);
1011
1012
return (vrtc);
1013
}
1014
1015
void
1016
vrtc_cleanup(struct vrtc *vrtc)
1017
{
1018
1019
callout_drain(&vrtc->callout);
1020
mtx_destroy(&vrtc->mtx);
1021
free(vrtc, M_VRTC);
1022
}
1023
1024
#ifdef BHYVE_SNAPSHOT
1025
int
1026
vrtc_snapshot(struct vrtc *vrtc, struct vm_snapshot_meta *meta)
1027
{
1028
int ret;
1029
1030
VRTC_LOCK(vrtc);
1031
1032
SNAPSHOT_VAR_OR_LEAVE(vrtc->addr, meta, ret, done);
1033
if (meta->op == VM_SNAPSHOT_RESTORE)
1034
vrtc->base_uptime = sbinuptime();
1035
SNAPSHOT_VAR_OR_LEAVE(vrtc->base_rtctime, meta, ret, done);
1036
1037
SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.sec, meta, ret, done);
1038
SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.alarm_sec, meta, ret, done);
1039
SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.min, meta, ret, done);
1040
SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.alarm_min, meta, ret, done);
1041
SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.hour, meta, ret, done);
1042
SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.alarm_hour, meta, ret, done);
1043
SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.day_of_week, meta, ret, done);
1044
SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.day_of_month, meta, ret, done);
1045
SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.month, meta, ret, done);
1046
SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.year, meta, ret, done);
1047
SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_a, meta, ret, done);
1048
SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_b, meta, ret, done);
1049
SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_c, meta, ret, done);
1050
SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.reg_d, meta, ret, done);
1051
SNAPSHOT_BUF_OR_LEAVE(vrtc->rtcdev.nvram, sizeof(vrtc->rtcdev.nvram),
1052
meta, ret, done);
1053
SNAPSHOT_VAR_OR_LEAVE(vrtc->rtcdev.century, meta, ret, done);
1054
SNAPSHOT_BUF_OR_LEAVE(vrtc->rtcdev.nvram2, sizeof(vrtc->rtcdev.nvram2),
1055
meta, ret, done);
1056
1057
vrtc_callout_reset(vrtc, vrtc_freq(vrtc));
1058
1059
VRTC_UNLOCK(vrtc);
1060
1061
done:
1062
return (ret);
1063
}
1064
#endif
1065
1066