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