1221828Sgrehan/*- 2221828Sgrehan * Copyright (c) 2011 NetApp, Inc. 3221828Sgrehan * All rights reserved. 4221828Sgrehan * 5221828Sgrehan * Redistribution and use in source and binary forms, with or without 6221828Sgrehan * modification, are permitted provided that the following conditions 7221828Sgrehan * are met: 8221828Sgrehan * 1. Redistributions of source code must retain the above copyright 9221828Sgrehan * notice, this list of conditions and the following disclaimer. 10221828Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 11221828Sgrehan * notice, this list of conditions and the following disclaimer in the 12221828Sgrehan * documentation and/or other materials provided with the distribution. 13221828Sgrehan * 14221828Sgrehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15221828Sgrehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16221828Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17221828Sgrehan * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18221828Sgrehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19221828Sgrehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20221828Sgrehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21221828Sgrehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22221828Sgrehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23221828Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24221828Sgrehan * SUCH DAMAGE. 25221828Sgrehan * 26221828Sgrehan * $FreeBSD: releng/10.2/usr.sbin/bhyve/rtc.c 284894 2015-06-27 22:48:22Z neel $ 27221828Sgrehan */ 28221828Sgrehan 29221828Sgrehan#include <sys/cdefs.h> 30221828Sgrehan__FBSDID("$FreeBSD: releng/10.2/usr.sbin/bhyve/rtc.c 284894 2015-06-27 22:48:22Z neel $"); 31221828Sgrehan 32221828Sgrehan#include <sys/types.h> 33221828Sgrehan 34221828Sgrehan#include <time.h> 35221828Sgrehan#include <assert.h> 36221828Sgrehan 37253181Sgrehan#include <machine/vmm.h> 38253181Sgrehan#include <vmmapi.h> 39253181Sgrehan 40261265Sjhb#include "acpi.h" 41261265Sjhb#include "pci_lpc.h" 42253181Sgrehan#include "rtc.h" 43221828Sgrehan 44284894Sneel#define IO_RTC 0x70 45221828Sgrehan 46253181Sgrehan#define RTC_LMEM_LSB 0x34 47253181Sgrehan#define RTC_LMEM_MSB 0x35 48253181Sgrehan#define RTC_HMEM_LSB 0x5b 49253181Sgrehan#define RTC_HMEM_SB 0x5c 50253181Sgrehan#define RTC_HMEM_MSB 0x5d 51222105Sgrehan 52253181Sgrehan#define m_64KB (64*1024) 53253181Sgrehan#define m_16MB (16*1024*1024) 54253181Sgrehan#define m_4GB (4ULL*1024*1024*1024) 55253181Sgrehan 56284894Sneel/* 57284894Sneel * Returns the current RTC time as number of seconds since 00:00:00 Jan 1, 1970 58284894Sneel */ 59284894Sneelstatic time_t 60284894Sneelrtc_time(struct vmctx *ctx, int use_localtime) 61221828Sgrehan{ 62284894Sneel struct tm tm; 63221828Sgrehan time_t t; 64221828Sgrehan 65284894Sneel time(&t); 66284894Sneel if (use_localtime) { 67221828Sgrehan localtime_r(&t, &tm); 68284894Sneel t = timegm(&tm); 69221828Sgrehan } 70284894Sneel return (t); 71221828Sgrehan} 72221828Sgrehan 73253181Sgrehanvoid 74284894Sneelrtc_init(struct vmctx *ctx, int use_localtime) 75253181Sgrehan{ 76253181Sgrehan size_t himem; 77253181Sgrehan size_t lomem; 78253181Sgrehan int err; 79253181Sgrehan 80253181Sgrehan /* XXX init diag/reset code/equipment/checksum ? */ 81253181Sgrehan 82253181Sgrehan /* 83253181Sgrehan * Report guest memory size in nvram cells as required by UEFI. 84253181Sgrehan * Little-endian encoding. 85253181Sgrehan * 0x34/0x35 - 64KB chunks above 16MB, below 4GB 86253181Sgrehan * 0x5b/0x5c/0x5d - 64KB chunks above 4GB 87253181Sgrehan */ 88270074Sgrehan lomem = (vm_get_lowmem_size(ctx) - m_16MB) / m_64KB; 89284894Sneel err = vm_rtc_write(ctx, RTC_LMEM_LSB, lomem); 90284894Sneel assert(err == 0); 91284894Sneel err = vm_rtc_write(ctx, RTC_LMEM_MSB, lomem >> 8); 92284894Sneel assert(err == 0); 93253181Sgrehan 94270074Sgrehan himem = vm_get_highmem_size(ctx) / m_64KB; 95284894Sneel err = vm_rtc_write(ctx, RTC_HMEM_LSB, himem); 96284894Sneel assert(err == 0); 97284894Sneel err = vm_rtc_write(ctx, RTC_HMEM_SB, himem >> 8); 98284894Sneel assert(err == 0); 99284894Sneel err = vm_rtc_write(ctx, RTC_HMEM_MSB, himem >> 16); 100284894Sneel assert(err == 0); 101284894Sneel 102284894Sneel err = vm_rtc_settime(ctx, rtc_time(ctx, use_localtime)); 103284894Sneel assert(err == 0); 104253181Sgrehan} 105253181Sgrehan 106261265Sjhbstatic void 107261265Sjhbrtc_dsdt(void) 108261265Sjhb{ 109261265Sjhb 110261265Sjhb dsdt_line(""); 111261265Sjhb dsdt_line("Device (RTC)"); 112261265Sjhb dsdt_line("{"); 113261265Sjhb dsdt_line(" Name (_HID, EisaId (\"PNP0B00\"))"); 114261265Sjhb dsdt_line(" Name (_CRS, ResourceTemplate ()"); 115261265Sjhb dsdt_line(" {"); 116261265Sjhb dsdt_indent(2); 117261265Sjhb dsdt_fixed_ioport(IO_RTC, 2); 118261265Sjhb dsdt_fixed_irq(8); 119261265Sjhb dsdt_unindent(2); 120261265Sjhb dsdt_line(" })"); 121261265Sjhb dsdt_line("}"); 122261265Sjhb} 123261265SjhbLPC_DSDT(rtc_dsdt); 124261265Sjhb 125276429Sneel/* 126276429Sneel * Reserve the extended RTC I/O ports although they are not emulated at this 127276429Sneel * time. 128276429Sneel */ 129261265SjhbSYSRES_IO(0x72, 6); 130