rtc.c revision 284894
1210040Scognet/*- 2213496Scognet * Copyright (c) 2011 NetApp, Inc. 3213496Scognet * All rights reserved. 4210040Scognet * 5210040Scognet * Redistribution and use in source and binary forms, with or without 6210040Scognet * modification, are permitted provided that the following conditions 7210040Scognet * are met: 8210040Scognet * 1. Redistributions of source code must retain the above copyright 9210040Scognet * notice, this list of conditions and the following disclaimer. 10210040Scognet * 2. Redistributions in binary form must reproduce the above copyright 11210040Scognet * notice, this list of conditions and the following disclaimer in the 12210040Scognet * documentation and/or other materials provided with the distribution. 13210040Scognet * 14210040Scognet * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15210040Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16210040Scognet * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17210040Scognet * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18210040Scognet * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19210040Scognet * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20210040Scognet * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21210040Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22210040Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23210040Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24210040Scognet * SUCH DAMAGE. 25210040Scognet * 26210040Scognet * $FreeBSD: stable/10/usr.sbin/bhyve/rtc.c 284894 2015-06-27 22:48:22Z neel $ 27266196Sian */ 28266196Sian 29210040Scognet#include <sys/cdefs.h> 30213496Scognet__FBSDID("$FreeBSD: stable/10/usr.sbin/bhyve/rtc.c 284894 2015-06-27 22:48:22Z neel $"); 31210040Scognet 32210040Scognet#include <sys/types.h> 33213496Scognet 34210040Scognet#include <time.h> 35210040Scognet#include <assert.h> 36213496Scognet 37213496Scognet#include <machine/vmm.h> 38213496Scognet#include <vmmapi.h> 39210040Scognet 40210040Scognet#include "acpi.h" 41210040Scognet#include "pci_lpc.h" 42210040Scognet#include "rtc.h" 43210040Scognet 44210040Scognet#define IO_RTC 0x70 45210040Scognet 46210040Scognet#define RTC_LMEM_LSB 0x34 47210040Scognet#define RTC_LMEM_MSB 0x35 48213496Scognet#define RTC_HMEM_LSB 0x5b 49210040Scognet#define RTC_HMEM_SB 0x5c 50210040Scognet#define RTC_HMEM_MSB 0x5d 51210040Scognet 52210040Scognet#define m_64KB (64*1024) 53266196Sian#define m_16MB (16*1024*1024) 54266196Sian#define m_4GB (4ULL*1024*1024*1024) 55266196Sian 56266196Sian/* 57266196Sian * Returns the current RTC time as number of seconds since 00:00:00 Jan 1, 1970 58266196Sian */ 59237130Simpstatic time_t 60237130Simprtc_time(struct vmctx *ctx, int use_localtime) 61237130Simp{ 62237130Simp struct tm tm; 63213496Scognet time_t t; 64213496Scognet 65213496Scognet time(&t); 66213496Scognet if (use_localtime) { 67213496Scognet localtime_r(&t, &tm); 68210040Scognet t = timegm(&tm); 69213496Scognet } 70238370Simp return (t); 71237130Simp} 72210040Scognet 73213496Scognetvoid 74213496Scognetrtc_init(struct vmctx *ctx, int use_localtime) 75213496Scognet{ 76234281Smarius size_t himem; 77213496Scognet size_t lomem; 78213496Scognet int err; 79210040Scognet 80213496Scognet /* XXX init diag/reset code/equipment/checksum ? */ 81213496Scognet 82213496Scognet /* 83234281Smarius * Report guest memory size in nvram cells as required by UEFI. 84213496Scognet * Little-endian encoding. 85213496Scognet * 0x34/0x35 - 64KB chunks above 16MB, below 4GB 86213496Scognet * 0x5b/0x5c/0x5d - 64KB chunks above 4GB 87238370Simp */ 88238370Simp lomem = (vm_get_lowmem_size(ctx) - m_16MB) / m_64KB; 89237130Simp err = vm_rtc_write(ctx, RTC_LMEM_LSB, lomem); 90237130Simp assert(err == 0); 91237130Simp err = vm_rtc_write(ctx, RTC_LMEM_MSB, lomem >> 8); 92237130Simp assert(err == 0); 93210040Scognet 94266196Sian himem = vm_get_highmem_size(ctx) / m_64KB; 95266196Sian err = vm_rtc_write(ctx, RTC_HMEM_LSB, himem); 96266196Sian assert(err == 0); 97237130Simp err = vm_rtc_write(ctx, RTC_HMEM_SB, himem >> 8); 98213496Scognet assert(err == 0); 99237130Simp err = vm_rtc_write(ctx, RTC_HMEM_MSB, himem >> 16); 100237130Simp assert(err == 0); 101237130Simp 102237130Simp err = vm_rtc_settime(ctx, rtc_time(ctx, use_localtime)); 103237130Simp assert(err == 0); 104237130Simp} 105237130Simp 106237130Simpstatic void 107237130Simprtc_dsdt(void) 108237130Simp{ 109237130Simp 110237130Simp dsdt_line(""); 111237130Simp dsdt_line("Device (RTC)"); 112237130Simp dsdt_line("{"); 113238370Simp dsdt_line(" Name (_HID, EisaId (\"PNP0B00\"))"); 114238370Simp dsdt_line(" Name (_CRS, ResourceTemplate ()"); 115210040Scognet dsdt_line(" {"); 116213496Scognet dsdt_indent(2); 117213496Scognet dsdt_fixed_ioport(IO_RTC, 2); 118213496Scognet dsdt_fixed_irq(8); 119210040Scognet dsdt_unindent(2); 120210040Scognet dsdt_line(" })"); 121210040Scognet dsdt_line("}"); 122210040Scognet} 123238370SimpLPC_DSDT(rtc_dsdt); 124210040Scognet 125266196Sian/* 126266196Sian * Reserve the extended RTC I/O ports although they are not emulated at this 127266196Sian * time. 128266196Sian */ 129237130SimpSYSRES_IO(0x72, 6); 130237130Simp