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