diff options
author | neel <neel@FreeBSD.org> | 2014-12-30 22:19:34 +0000 |
---|---|---|
committer | neel <neel@FreeBSD.org> | 2014-12-30 22:19:34 +0000 |
commit | 7aa6460c481c4da0a3c093bed060275c1dc56dec (patch) | |
tree | 0751604dc4d91153ec1742651bba58911187d665 /usr.sbin/bhyvectl | |
parent | 65848ba7938d637d57541ab63b36c13518926c9f (diff) | |
download | FreeBSD-src-7aa6460c481c4da0a3c093bed060275c1dc56dec.zip FreeBSD-src-7aa6460c481c4da0a3c093bed060275c1dc56dec.tar.gz |
Replace bhyve's minimal RTC emulation with a fully featured one in vmm.ko.
The new RTC emulation supports all interrupt modes: periodic, update ended
and alarm. It is also capable of maintaining the date/time and NVRAM contents
across virtual machine reset. Also, the date/time fields can now be modified
by the guest.
Since bhyve now emulates both the PIT and the RTC there is no need for
"Legacy Replacement Routing" in the HPET so get rid of it.
The RTC device state can be inspected via bhyvectl as follows:
bhyvectl --vm=vm --get-rtc-time
bhyvectl --vm=vm --set-rtc-time=<unix_time_secs>
bhyvectl --vm=vm --rtc-nvram-offset=<offset> --get-rtc-nvram
bhyvectl --vm=vm --rtc-nvram-offset=<offset> --set-rtc-nvram=<value>
Reviewed by: tychon
Discussed with: grehan
Differential Revision: https://reviews.freebsd.org/D1385
MFC after: 2 weeks
Diffstat (limited to 'usr.sbin/bhyvectl')
-rw-r--r-- | usr.sbin/bhyvectl/bhyvectl.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/usr.sbin/bhyvectl/bhyvectl.c b/usr.sbin/bhyvectl/bhyvectl.c index 0c4457e..170ca21 100644 --- a/usr.sbin/bhyvectl/bhyvectl.c +++ b/usr.sbin/bhyvectl/bhyvectl.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #include <fcntl.h> #include <string.h> #include <getopt.h> +#include <time.h> #include <assert.h> #include <machine/cpufunc.h> @@ -157,6 +158,11 @@ usage(bool cpu_intel) " [--inject-nmi]\n" " [--force-reset]\n" " [--force-poweroff]\n" + " [--get-rtc-time]\n" + " [--set-rtc-time=<secs>]\n" + " [--get-rtc-nvram]\n" + " [--set-rtc-nvram=<val>]\n" + " [--rtc-nvram-offset=<offset>]\n" " [--get-active-cpus]\n" " [--get-suspended-cpus]\n" " [--get-intinfo]\n" @@ -220,6 +226,12 @@ usage(bool cpu_intel) exit(1); } +static int get_rtc_time, set_rtc_time; +static int get_rtc_nvram, set_rtc_nvram; +static int rtc_nvram_offset; +static uint8_t rtc_nvram_value; +static time_t rtc_secs; + static int get_stats, getcap, setcap, capval, get_gpa_pmap; static int inject_nmi, assert_lapic_lvt; static int force_reset, force_poweroff; @@ -545,6 +557,9 @@ enum { UNASSIGN_PPTDEV, GET_GPA_PMAP, ASSERT_LAPIC_LVT, + SET_RTC_TIME, + SET_RTC_NVRAM, + RTC_NVRAM_OFFSET, }; static void @@ -1269,6 +1284,11 @@ setup_options(bool cpu_intel) { "setcap", REQ_ARG, 0, SET_CAP }, { "get-gpa-pmap", REQ_ARG, 0, GET_GPA_PMAP }, { "assert-lapic-lvt", REQ_ARG, 0, ASSERT_LAPIC_LVT }, + { "get-rtc-time", NO_ARG, &get_rtc_time, 1 }, + { "set-rtc-time", REQ_ARG, 0, SET_RTC_TIME }, + { "rtc-nvram-offset", REQ_ARG, 0, RTC_NVRAM_OFFSET }, + { "get-rtc-nvram", NO_ARG, &get_rtc_nvram, 1 }, + { "set-rtc-nvram", REQ_ARG, 0, SET_RTC_NVRAM }, { "getcap", NO_ARG, &getcap, 1 }, { "get-stats", NO_ARG, &get_stats, 1 }, { "get-desc-ds",NO_ARG, &get_desc_ds, 1 }, @@ -1462,6 +1482,33 @@ setup_options(bool cpu_intel) return (all_opts); } +static const char * +wday_str(int idx) +{ + static const char *weekdays[] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" + }; + + if (idx >= 0 && idx < 7) + return (weekdays[idx]); + else + return ("UNK"); +} + +static const char * +mon_str(int idx) +{ + static const char *months[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + + if (idx >= 0 && idx < 12) + return (months[idx]); + else + return ("UNK"); +} + int main(int argc, char *argv[]) { @@ -1477,6 +1524,7 @@ main(int argc, char *argv[]) cpuset_t cpus; bool cpu_intel; uint64_t cs, ds, es, fs, gs, ss, tr, ldtr; + struct tm tm; struct option *opts; cpu_intel = cpu_vendor_intel(); @@ -1594,6 +1642,17 @@ main(int argc, char *argv[]) capval = strtoul(optarg, NULL, 0); setcap = 1; break; + case SET_RTC_TIME: + rtc_secs = strtoul(optarg, NULL, 0); + set_rtc_time = 1; + break; + case SET_RTC_NVRAM: + rtc_nvram_value = (uint8_t)strtoul(optarg, NULL, 0); + set_rtc_nvram = 1; + break; + case RTC_NVRAM_OFFSET: + rtc_nvram_offset = strtoul(optarg, NULL, 0); + break; case GET_GPA_PMAP: gpa_pmap = strtoul(optarg, NULL, 0); get_gpa_pmap = 1; @@ -1971,6 +2030,31 @@ main(int argc, char *argv[]) } } + if (!error && set_rtc_nvram) + error = vm_rtc_write(ctx, rtc_nvram_offset, rtc_nvram_value); + + if (!error && (get_rtc_nvram || get_all)) { + error = vm_rtc_read(ctx, rtc_nvram_offset, &rtc_nvram_value); + if (error == 0) { + printf("rtc nvram[%03d]: 0x%02x\n", rtc_nvram_offset, + rtc_nvram_value); + } + } + + if (!error && set_rtc_time) + error = vm_rtc_settime(ctx, rtc_secs); + + if (!error && (get_rtc_time || get_all)) { + error = vm_rtc_gettime(ctx, &rtc_secs); + if (error == 0) { + gmtime_r(&rtc_secs, &tm); + printf("rtc time %#lx: %s %s %02d %02d:%02d:%02d %d\n", + rtc_secs, wday_str(tm.tm_wday), mon_str(tm.tm_mon), + tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, + 1900 + tm.tm_year); + } + } + if (!error && (getcap || get_all)) { int captype, val, getcaptype; |