xref: /illumos-gate/usr/src/cmd/bhyve/amd64/rtc.c (revision 5c4a5fe16715fb423db76577a6883b5bbecdbe45)
1*5c4a5fe1SAndy Fiddaman /*-
2*5c4a5fe1SAndy Fiddaman  * SPDX-License-Identifier: BSD-2-Clause
3*5c4a5fe1SAndy Fiddaman  *
4*5c4a5fe1SAndy Fiddaman  * Copyright (c) 2011 NetApp, Inc.
5*5c4a5fe1SAndy Fiddaman  * All rights reserved.
6*5c4a5fe1SAndy Fiddaman  *
7*5c4a5fe1SAndy Fiddaman  * Redistribution and use in source and binary forms, with or without
8*5c4a5fe1SAndy Fiddaman  * modification, are permitted provided that the following conditions
9*5c4a5fe1SAndy Fiddaman  * are met:
10*5c4a5fe1SAndy Fiddaman  * 1. Redistributions of source code must retain the above copyright
11*5c4a5fe1SAndy Fiddaman  *    notice, this list of conditions and the following disclaimer.
12*5c4a5fe1SAndy Fiddaman  * 2. Redistributions in binary form must reproduce the above copyright
13*5c4a5fe1SAndy Fiddaman  *    notice, this list of conditions and the following disclaimer in the
14*5c4a5fe1SAndy Fiddaman  *    documentation and/or other materials provided with the distribution.
15*5c4a5fe1SAndy Fiddaman  *
16*5c4a5fe1SAndy Fiddaman  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
17*5c4a5fe1SAndy Fiddaman  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*5c4a5fe1SAndy Fiddaman  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*5c4a5fe1SAndy Fiddaman  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
20*5c4a5fe1SAndy Fiddaman  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*5c4a5fe1SAndy Fiddaman  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*5c4a5fe1SAndy Fiddaman  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*5c4a5fe1SAndy Fiddaman  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*5c4a5fe1SAndy Fiddaman  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*5c4a5fe1SAndy Fiddaman  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*5c4a5fe1SAndy Fiddaman  * SUCH DAMAGE.
27*5c4a5fe1SAndy Fiddaman  */
28*5c4a5fe1SAndy Fiddaman 
29*5c4a5fe1SAndy Fiddaman 
30*5c4a5fe1SAndy Fiddaman #include <sys/types.h>
31*5c4a5fe1SAndy Fiddaman 
32*5c4a5fe1SAndy Fiddaman #include <time.h>
33*5c4a5fe1SAndy Fiddaman #include <assert.h>
34*5c4a5fe1SAndy Fiddaman 
35*5c4a5fe1SAndy Fiddaman #include <machine/vmm.h>
36*5c4a5fe1SAndy Fiddaman #include <vmmapi.h>
37*5c4a5fe1SAndy Fiddaman 
38*5c4a5fe1SAndy Fiddaman #include "acpi.h"
39*5c4a5fe1SAndy Fiddaman #include "config.h"
40*5c4a5fe1SAndy Fiddaman #include "pci_lpc.h"
41*5c4a5fe1SAndy Fiddaman #include "rtc.h"
42*5c4a5fe1SAndy Fiddaman 
43*5c4a5fe1SAndy Fiddaman #define	IO_RTC		0x70
44*5c4a5fe1SAndy Fiddaman 
45*5c4a5fe1SAndy Fiddaman #define	RTC_LMEM_LSB	0x34
46*5c4a5fe1SAndy Fiddaman #define	RTC_LMEM_MSB	0x35
47*5c4a5fe1SAndy Fiddaman #define	RTC_HMEM_LSB	0x5b
48*5c4a5fe1SAndy Fiddaman #define	RTC_HMEM_SB	0x5c
49*5c4a5fe1SAndy Fiddaman #define	RTC_HMEM_MSB	0x5d
50*5c4a5fe1SAndy Fiddaman 
51*5c4a5fe1SAndy Fiddaman #define	m_64KB		(64*1024)
52*5c4a5fe1SAndy Fiddaman #define	m_16MB		(16*1024*1024)
53*5c4a5fe1SAndy Fiddaman #define	m_4GB		(4ULL*1024*1024*1024)
54*5c4a5fe1SAndy Fiddaman 
55*5c4a5fe1SAndy Fiddaman /*
56*5c4a5fe1SAndy Fiddaman  * Returns the current RTC time as number of seconds since 00:00:00 Jan 1, 1970
57*5c4a5fe1SAndy Fiddaman  */
58*5c4a5fe1SAndy Fiddaman #ifdef __FreeBSD__
59*5c4a5fe1SAndy Fiddaman static time_t
rtc_time(void)60*5c4a5fe1SAndy Fiddaman rtc_time(void)
61*5c4a5fe1SAndy Fiddaman {
62*5c4a5fe1SAndy Fiddaman 	struct tm tm;
63*5c4a5fe1SAndy Fiddaman 	time_t t;
64*5c4a5fe1SAndy Fiddaman 
65*5c4a5fe1SAndy Fiddaman 	time(&t);
66*5c4a5fe1SAndy Fiddaman 	if (get_config_bool_default("rtc.use_localtime", true)) {
67*5c4a5fe1SAndy Fiddaman 		localtime_r(&t, &tm);
68*5c4a5fe1SAndy Fiddaman 		t = timegm(&tm);
69*5c4a5fe1SAndy Fiddaman 	}
70*5c4a5fe1SAndy Fiddaman 	return (t);
71*5c4a5fe1SAndy Fiddaman }
72*5c4a5fe1SAndy Fiddaman #else /* __FreeBSD__ */
73*5c4a5fe1SAndy Fiddaman static void
rtc_time(timespec_t * ts)74*5c4a5fe1SAndy Fiddaman rtc_time(timespec_t *ts)
75*5c4a5fe1SAndy Fiddaman {
76*5c4a5fe1SAndy Fiddaman 	(void) clock_gettime(CLOCK_REALTIME, ts);
77*5c4a5fe1SAndy Fiddaman 
78*5c4a5fe1SAndy Fiddaman 	if (get_config_bool_default("rtc.use_localtime", true)) {
79*5c4a5fe1SAndy Fiddaman 		struct tm tm;
80*5c4a5fe1SAndy Fiddaman 
81*5c4a5fe1SAndy Fiddaman 		localtime_r(&ts->tv_sec, &tm);
82*5c4a5fe1SAndy Fiddaman 		ts->tv_sec = timegm(&tm);
83*5c4a5fe1SAndy Fiddaman 	}
84*5c4a5fe1SAndy Fiddaman }
85*5c4a5fe1SAndy Fiddaman #endif /* __FreeBSD__ */
86*5c4a5fe1SAndy Fiddaman 
87*5c4a5fe1SAndy Fiddaman void
rtc_init(struct vmctx * ctx)88*5c4a5fe1SAndy Fiddaman rtc_init(struct vmctx *ctx)
89*5c4a5fe1SAndy Fiddaman {
90*5c4a5fe1SAndy Fiddaman 	size_t himem;
91*5c4a5fe1SAndy Fiddaman 	size_t lomem;
92*5c4a5fe1SAndy Fiddaman 	int err;
93*5c4a5fe1SAndy Fiddaman 
94*5c4a5fe1SAndy Fiddaman 	/* XXX init diag/reset code/equipment/checksum ? */
95*5c4a5fe1SAndy Fiddaman 
96*5c4a5fe1SAndy Fiddaman 	/*
97*5c4a5fe1SAndy Fiddaman 	 * Report guest memory size in nvram cells as required by UEFI.
98*5c4a5fe1SAndy Fiddaman 	 * Little-endian encoding.
99*5c4a5fe1SAndy Fiddaman 	 * 0x34/0x35 - 64KB chunks above 16MB, below 4GB
100*5c4a5fe1SAndy Fiddaman 	 * 0x5b/0x5c/0x5d - 64KB chunks above 4GB
101*5c4a5fe1SAndy Fiddaman 	 */
102*5c4a5fe1SAndy Fiddaman 	lomem = (vm_get_lowmem_size(ctx) - m_16MB) / m_64KB;
103*5c4a5fe1SAndy Fiddaman 	err = vm_rtc_write(ctx, RTC_LMEM_LSB, lomem);
104*5c4a5fe1SAndy Fiddaman 	assert(err == 0);
105*5c4a5fe1SAndy Fiddaman 	err = vm_rtc_write(ctx, RTC_LMEM_MSB, lomem >> 8);
106*5c4a5fe1SAndy Fiddaman 	assert(err == 0);
107*5c4a5fe1SAndy Fiddaman 
108*5c4a5fe1SAndy Fiddaman 	himem = vm_get_highmem_size(ctx) / m_64KB;
109*5c4a5fe1SAndy Fiddaman 	err = vm_rtc_write(ctx, RTC_HMEM_LSB, himem);
110*5c4a5fe1SAndy Fiddaman 	assert(err == 0);
111*5c4a5fe1SAndy Fiddaman 	err = vm_rtc_write(ctx, RTC_HMEM_SB, himem >> 8);
112*5c4a5fe1SAndy Fiddaman 	assert(err == 0);
113*5c4a5fe1SAndy Fiddaman 	err = vm_rtc_write(ctx, RTC_HMEM_MSB, himem >> 16);
114*5c4a5fe1SAndy Fiddaman 	assert(err == 0);
115*5c4a5fe1SAndy Fiddaman 
116*5c4a5fe1SAndy Fiddaman #ifdef __FreeBSD__
117*5c4a5fe1SAndy Fiddaman 	err = vm_rtc_settime(ctx, rtc_time());
118*5c4a5fe1SAndy Fiddaman #else
119*5c4a5fe1SAndy Fiddaman 	timespec_t ts;
120*5c4a5fe1SAndy Fiddaman 
121*5c4a5fe1SAndy Fiddaman 	rtc_time(&ts);
122*5c4a5fe1SAndy Fiddaman 	err = vm_rtc_settime(ctx, &ts);
123*5c4a5fe1SAndy Fiddaman #endif
124*5c4a5fe1SAndy Fiddaman 	assert(err == 0);
125*5c4a5fe1SAndy Fiddaman }
126*5c4a5fe1SAndy Fiddaman 
127*5c4a5fe1SAndy Fiddaman static void
rtc_dsdt(void)128*5c4a5fe1SAndy Fiddaman rtc_dsdt(void)
129*5c4a5fe1SAndy Fiddaman {
130*5c4a5fe1SAndy Fiddaman 
131*5c4a5fe1SAndy Fiddaman 	dsdt_line("");
132*5c4a5fe1SAndy Fiddaman 	dsdt_line("Device (RTC)");
133*5c4a5fe1SAndy Fiddaman 	dsdt_line("{");
134*5c4a5fe1SAndy Fiddaman 	dsdt_line("  Name (_HID, EisaId (\"PNP0B00\"))");
135*5c4a5fe1SAndy Fiddaman 	dsdt_line("  Name (_CRS, ResourceTemplate ()");
136*5c4a5fe1SAndy Fiddaman 	dsdt_line("  {");
137*5c4a5fe1SAndy Fiddaman 	dsdt_indent(2);
138*5c4a5fe1SAndy Fiddaman 	dsdt_fixed_ioport(IO_RTC, 2);
139*5c4a5fe1SAndy Fiddaman 	dsdt_fixed_irq(8);
140*5c4a5fe1SAndy Fiddaman 	dsdt_unindent(2);
141*5c4a5fe1SAndy Fiddaman 	dsdt_line("  })");
142*5c4a5fe1SAndy Fiddaman 	dsdt_line("}");
143*5c4a5fe1SAndy Fiddaman }
144*5c4a5fe1SAndy Fiddaman LPC_DSDT(rtc_dsdt);
145*5c4a5fe1SAndy Fiddaman 
146*5c4a5fe1SAndy Fiddaman /*
147*5c4a5fe1SAndy Fiddaman  * Reserve the extended RTC I/O ports although they are not emulated at this
148*5c4a5fe1SAndy Fiddaman  * time.
149*5c4a5fe1SAndy Fiddaman  */
150*5c4a5fe1SAndy Fiddaman SYSRES_IO(0x72, 6);
151