From 9d6be09f8a5e7460f8905f0777fe493fa2e9bdfa Mon Sep 17 00:00:00 2001 From: Peter Grehan Date: Thu, 11 Jul 2013 03:54:35 +0000 Subject: [PATCH] Implement RTC CMOS nvram. Init some fields that are used by FreeBSD and UEFI. Tested with nvram(4). Reviewed by: neel --- usr.sbin/bhyve/bhyverun.c | 3 ++ usr.sbin/bhyve/rtc.c | 90 +++++++++++++++++++++++++++++---------- usr.sbin/bhyve/rtc.h | 34 +++++++++++++++ 3 files changed, 105 insertions(+), 22 deletions(-) create mode 100644 usr.sbin/bhyve/rtc.h diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c index ae22de25f093..cfcf7ecf6d2d 100644 --- a/usr.sbin/bhyve/bhyverun.c +++ b/usr.sbin/bhyve/bhyverun.c @@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$"); #include "xmsr.h" #include "ioapic.h" #include "spinup_ap.h" +#include "rtc.h" #define DEFAULT_GUEST_HZ 100 #define DEFAULT_GUEST_TSLICE 200 @@ -735,6 +736,8 @@ main(int argc, char *argv[]) init_mem(); init_inout(); + rtc_init(ctx); + /* * Exit if a device emulation finds an error in it's initilization */ diff --git a/usr.sbin/bhyve/rtc.c b/usr.sbin/bhyve/rtc.c index df21ac8ddbfd..a0e2c6a5c5c5 100644 --- a/usr.sbin/bhyve/rtc.c +++ b/usr.sbin/bhyve/rtc.c @@ -33,10 +33,15 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include +#include +#include + #include "inout.h" +#include "rtc.h" #define IO_RTC 0x70 @@ -64,16 +69,30 @@ __FBSDID("$FreeBSD$"); #define RTC_STATUSD 0x0d /* status register D (R) Lost Power */ #define RTCSD_PWR 0x80 /* clock power OK */ +#define RTC_NVRAM_START 0x0e +#define RTC_NVRAM_END 0x7f +#define RTC_NVRAM_SZ (128 - RTC_NVRAM_START) +#define nvoff(x) ((x) - RTC_NVRAM_START) + #define RTC_DIAG 0x0e - #define RTC_RSTCODE 0x0f - #define RTC_EQUIPMENT 0x14 +#define RTC_LMEM_LSB 0x34 +#define RTC_LMEM_MSB 0x35 +#define RTC_HMEM_LSB 0x5b +#define RTC_HMEM_SB 0x5c +#define RTC_HMEM_MSB 0x5d + +#define m_64KB (64*1024) +#define m_16MB (16*1024*1024) +#define m_4GB (4ULL*1024*1024*1024) static int addr; +static uint8_t rtc_nvram[RTC_NVRAM_SZ]; + /* XXX initialize these to default values as they would be from BIOS */ -static uint8_t status_a, status_b, rstcode; +static uint8_t status_a, status_b; static u_char const bin2bcd_data[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, @@ -135,14 +154,11 @@ rtc_addr_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, case RTC_DAY: case RTC_MONTH: case RTC_YEAR: - case RTC_CENTURY: case RTC_STATUSA: case RTC_STATUSB: case RTC_INTR: case RTC_STATUSD: - case RTC_DIAG: - case RTC_RSTCODE: - case RTC_EQUIPMENT: + case RTC_NVRAM_START ... RTC_NVRAM_END: break; default: return (-1); @@ -217,9 +233,6 @@ rtc_data_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, case RTC_YEAR: *eax = rtcout(tm.tm_year % 100); return (0); - case RTC_CENTURY: - *eax = rtcout(tm.tm_year / 100); - break; case RTC_STATUSA: *eax = status_a; return (0); @@ -232,14 +245,8 @@ rtc_data_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, case RTC_STATUSD: *eax = RTCSD_PWR; return (0); - case RTC_DIAG: - *eax = 0; - return (0); - case RTC_RSTCODE: - *eax = rstcode; - return (0); - case RTC_EQUIPMENT: - *eax = 0; + case RTC_NVRAM_START ... RTC_NVRAM_END: + *eax = rtc_nvram[addr - RTC_NVRAM_START]; return (0); default: return (-1); @@ -259,9 +266,6 @@ rtc_data_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, case RTC_STATUSD: /* ignore write */ break; - case RTC_RSTCODE: - rstcode = *eax; - break; case RTC_SEC: case RTC_MIN: case RTC_HRS: @@ -269,16 +273,58 @@ rtc_data_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, case RTC_DAY: case RTC_MONTH: case RTC_YEAR: - case RTC_CENTURY: /* * Ignore writes to the time of day registers */ break; + case RTC_NVRAM_START ... RTC_NVRAM_END: + rtc_nvram[addr - RTC_NVRAM_START] = *eax; + break; default: return (-1); } return (0); } +void +rtc_init(struct vmctx *ctx) +{ + struct timeval cur; + struct tm tm; + size_t himem; + size_t lomem; + int err; + + err = gettimeofday(&cur, NULL); + assert(err == 0); + (void) localtime_r(&cur.tv_sec, &tm); + + memset(rtc_nvram, 0, sizeof(rtc_nvram)); + + rtc_nvram[nvoff(RTC_CENTURY)] = rtcout(tm.tm_year / 100); + + /* XXX init diag/reset code/equipment/checksum ? */ + + /* + * Report guest memory size in nvram cells as required by UEFI. + * Little-endian encoding. + * 0x34/0x35 - 64KB chunks above 16MB, below 4GB + * 0x5b/0x5c/0x5d - 64KB chunks above 4GB + */ + err = vm_get_memory_seg(ctx, 0, &lomem); + assert(err == 0); + + lomem = (lomem - m_16MB) / m_64KB; + rtc_nvram[nvoff(RTC_LMEM_LSB)] = lomem; + rtc_nvram[nvoff(RTC_LMEM_MSB)] = lomem >> 8; + + if (vm_get_memory_seg(ctx, m_4GB, &himem) == 0) { + himem /= m_64KB; + rtc_nvram[nvoff(RTC_HMEM_LSB)] = himem; + rtc_nvram[nvoff(RTC_HMEM_SB)] = himem >> 8; + rtc_nvram[nvoff(RTC_NVRAM_START)] = himem >> 16; + } +} + INOUT_PORT(rtc, IO_RTC, IOPORT_F_INOUT, rtc_addr_handler); INOUT_PORT(rtc, IO_RTC + 1, IOPORT_F_INOUT, rtc_data_handler); diff --git a/usr.sbin/bhyve/rtc.h b/usr.sbin/bhyve/rtc.h new file mode 100644 index 000000000000..72cffb3b09b7 --- /dev/null +++ b/usr.sbin/bhyve/rtc.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013 Peter Grehan + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _RTC_H_ +#define _RTC_H_ + +void rtc_init(struct vmctx *ctx); + +#endif /* _RTC_H_ */