summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bhyve
diff options
context:
space:
mode:
authorgrehan <grehan@FreeBSD.org>2013-07-11 03:54:35 +0000
committergrehan <grehan@FreeBSD.org>2013-07-11 03:54:35 +0000
commitdb9a28132c49cbcb4f9fe8a7dc4eab2f9c6b8e85 (patch)
tree13b1681daf5abca8f25a1fa0669e3281fa481b7e /usr.sbin/bhyve
parent7e7c09d9732434001b6214583188bf7b1125df30 (diff)
downloadFreeBSD-src-db9a28132c49cbcb4f9fe8a7dc4eab2f9c6b8e85.zip
FreeBSD-src-db9a28132c49cbcb4f9fe8a7dc4eab2f9c6b8e85.tar.gz
Implement RTC CMOS nvram. Init some fields that are used
by FreeBSD and UEFI. Tested with nvram(4). Reviewed by: neel
Diffstat (limited to 'usr.sbin/bhyve')
-rw-r--r--usr.sbin/bhyve/bhyverun.c3
-rw-r--r--usr.sbin/bhyve/rtc.c90
-rw-r--r--usr.sbin/bhyve/rtc.h34
3 files changed, 105 insertions, 22 deletions
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
index ae22de2..cfcf7ec 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 df21ac8..a0e2c6a 100644
--- a/usr.sbin/bhyve/rtc.c
+++ b/usr.sbin/bhyve/rtc.c
@@ -33,10 +33,15 @@ __FBSDID("$FreeBSD$");
#include <sys/time.h>
#include <stdio.h>
+#include <string.h>
#include <time.h>
#include <assert.h>
+#include <machine/vmm.h>
+#include <vmmapi.h>
+
#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_DIAG 0x0e
+#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 0000000..72cffb3
--- /dev/null
+++ b/usr.sbin/bhyve/rtc.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 Peter Grehan <grehan@freebsd.org>
+ * 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_ */
OpenPOWER on IntegriCloud