summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Mooney <pmooney@pfmooney.com>2018-04-25 20:05:05 +0000
committerPatrick Mooney <pmooney@pfmooney.com>2018-06-19 14:53:28 +0000
commit4f723dcffd015c7d11cd1c7a3155f46aa0600646 (patch)
treead36a6135b2ce9020ad402cc19f844306801cd9c
parent967bcd4bf4ed12e06a616379429f6f1a8765bbe4 (diff)
downloadillumos-joyent-4f723dcffd015c7d11cd1c7a3155f46aa0600646.tar.gz
OS-6923 bhyve could be more precise with vPIT
OS-6849 bhyve should localize vatpit resources Reviewed by: Hans Rosenfeld <hans.rosenfeld@joyent.com> Reviewed by: Dan McDonald <danmcd@joyent.com> Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r--usr/src/compat/freebsd/sys/time.h10
-rw-r--r--usr/src/uts/i86pc/io/vmm/io/vatpit.c82
-rw-r--r--usr/src/uts/i86pc/io/vmm/io/vatpit.h4
-rw-r--r--usr/src/uts/i86pc/io/vmm/vmm.c1
4 files changed, 71 insertions, 26 deletions
diff --git a/usr/src/compat/freebsd/sys/time.h b/usr/src/compat/freebsd/sys/time.h
index b63fd7fa4a..4e0fbfc02c 100644
--- a/usr/src/compat/freebsd/sys/time.h
+++ b/usr/src/compat/freebsd/sys/time.h
@@ -100,6 +100,16 @@ bttosbt(const struct bintime bt)
return (((sbintime_t)bt.sec << 32) + (bt.frac >> 32));
}
+static __inline struct bintime
+sbttobt(sbintime_t _sbt)
+{
+ struct bintime _bt;
+
+ _bt.sec = _sbt >> 32;
+ _bt.frac = _sbt << 32;
+ return (_bt);
+}
+
static __inline sbintime_t
sbinuptime(void)
{
diff --git a/usr/src/uts/i86pc/io/vmm/io/vatpit.c b/usr/src/uts/i86pc/io/vmm/io/vatpit.c
index d39c759f77..9b3e7376d5 100644
--- a/usr/src/uts/i86pc/io/vmm/io/vatpit.c
+++ b/usr/src/uts/i86pc/io/vmm/io/vatpit.c
@@ -1,4 +1,5 @@
/*-
+ * Copyright (c) 2018 Joyent, Inc.
* Copyright (c) 2014 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com>
* Copyright (c) 2011 NetApp, Inc.
* All rights reserved.
@@ -78,7 +79,7 @@ struct vatpit_callout_arg {
struct channel {
int mode;
uint16_t initial; /* initial counter value */
- sbintime_t now_sbt; /* uptime when counter was loaded */
+ struct bintime now_bt; /* uptime when counter was loaded */
uint8_t cr[2];
uint8_t ol[2];
bool slatched; /* status latched */
@@ -87,7 +88,7 @@ struct channel {
int olbyte;
int frbyte;
struct callout callout;
- sbintime_t callout_sbt; /* target time */
+ struct bintime callout_bt; /* target time */
struct vatpit_callout_arg callout_arg;
};
@@ -95,26 +96,41 @@ struct vatpit {
struct vm *vm;
struct mtx mtx;
- sbintime_t freq_sbt;
+ struct bintime freq_bt;
struct channel channel[3];
};
static void pit_timer_start_cntr0(struct vatpit *vatpit);
+static uint64_t
+vatpit_delta_ticks(struct vatpit *vatpit, struct channel *c)
+{
+ struct bintime delta;
+ uint64_t result;
+
+ binuptime(&delta);
+ bintime_sub(&delta, &c->now_bt);
+
+ result = delta.sec * PIT_8254_FREQ;
+ result += delta.frac / vatpit->freq_bt.frac;
+
+ return (result);
+}
+
static int
vatpit_get_out(struct vatpit *vatpit, int channel)
{
struct channel *c;
- sbintime_t delta_ticks;
+ uint64_t delta_ticks;
int out;
c = &vatpit->channel[channel];
switch (c->mode) {
case TIMER_INTTC:
- delta_ticks = (sbinuptime() - c->now_sbt) / vatpit->freq_sbt;
- out = ((c->initial - delta_ticks) <= 0);
+ delta_ticks = vatpit_delta_ticks(vatpit, c);
+ out = (delta_ticks >= c->initial);
break;
default:
out = 0;
@@ -164,24 +180,28 @@ static void
pit_timer_start_cntr0(struct vatpit *vatpit)
{
struct channel *c;
- sbintime_t now, delta, precision;
c = &vatpit->channel[0];
if (c->initial != 0) {
- delta = c->initial * vatpit->freq_sbt;
- precision = delta >> tc_precexp;
- c->callout_sbt = c->callout_sbt + delta;
+ sbintime_t precision;
+ struct bintime now, delta;
+
+ delta.sec = 0;
+ delta.frac = vatpit->freq_bt.frac * c->initial;
+ bintime_add(&c->callout_bt, &delta);
+ precision = bttosbt(delta) >> tc_precexp;
/*
- * Reset 'callout_sbt' if the time that the callout
- * was supposed to fire is more than 'c->initial'
- * ticks in the past.
+ * Reset 'callout_bt' if the time that the callout was supposed
+ * to fire is more than 'c->initial' ticks in the past.
*/
- now = sbinuptime();
- if (c->callout_sbt < now)
- c->callout_sbt = now + delta;
+ binuptime(&now);
+ if (bintime_cmp(&c->callout_bt, &now, <)) {
+ c->callout_bt = now;
+ bintime_add(&c->callout_bt, &delta);
+ }
- callout_reset_sbt(&c->callout, c->callout_sbt,
+ callout_reset_sbt(&c->callout, bttosbt(c->callout_bt),
precision, vatpit_callout_handler, &c->callout_arg,
C_ABSOLUTE);
}
@@ -191,7 +211,7 @@ static uint16_t
pit_update_counter(struct vatpit *vatpit, struct channel *c, bool latch)
{
uint16_t lval;
- sbintime_t delta_ticks;
+ uint64_t delta_ticks;
/* cannot latch a new value until the old one has been consumed */
if (latch && c->olbyte != 0)
@@ -207,12 +227,11 @@ pit_update_counter(struct vatpit *vatpit, struct channel *c, bool latch)
* here.
*/
c->initial = TIMER_DIV(PIT_8254_FREQ, 100);
- c->now_sbt = sbinuptime();
+ binuptime(&c->now_bt);
c->status &= ~TIMER_STS_NULLCNT;
}
- delta_ticks = (sbinuptime() - c->now_sbt) / vatpit->freq_sbt;
-
+ delta_ticks = vatpit_delta_ticks(vatpit, c);
lval = c->initial - delta_ticks % c->initial;
if (latch) {
@@ -383,10 +402,10 @@ vatpit_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
c->frbyte = 0;
c->crbyte = 0;
c->initial = c->cr[0] | (uint16_t)c->cr[1] << 8;
- c->now_sbt = sbinuptime();
+ binuptime(&c->now_bt);
/* Start an interval timer for channel 0 */
if (port == TIMER_CNTR0) {
- c->callout_sbt = c->now_sbt;
+ c->callout_bt = c->now_bt;
pit_timer_start_cntr0(vatpit);
}
if (c->initial == 0)
@@ -423,7 +442,6 @@ struct vatpit *
vatpit_init(struct vm *vm)
{
struct vatpit *vatpit;
- struct bintime bt;
struct vatpit_callout_arg *arg;
int i;
@@ -432,8 +450,7 @@ vatpit_init(struct vm *vm)
mtx_init(&vatpit->mtx, "vatpit lock", NULL, MTX_SPIN);
- FREQ2BT(PIT_8254_FREQ, &bt);
- vatpit->freq_sbt = bttosbt(bt);
+ FREQ2BT(PIT_8254_FREQ, &vatpit->freq_bt);
for (i = 0; i < 3; i++) {
callout_init(&vatpit->channel[i].callout, 1);
@@ -455,3 +472,16 @@ vatpit_cleanup(struct vatpit *vatpit)
free(vatpit, M_VATPIT);
}
+
+#ifndef __FreeBSD__
+void
+vatpit_localize_resources(struct vatpit *vatpit)
+{
+ for (uint_t i = 0; i < 3; i++) {
+ /* Only localize channels which might be running */
+ if (vatpit->channel[i].mode != 0) {
+ vmm_glue_callout_localize(&vatpit->channel[i].callout);
+ }
+ }
+}
+#endif /* __FreeBSD */
diff --git a/usr/src/uts/i86pc/io/vmm/io/vatpit.h b/usr/src/uts/i86pc/io/vmm/io/vatpit.h
index 5719c9c1aa..12f2db2c61 100644
--- a/usr/src/uts/i86pc/io/vmm/io/vatpit.h
+++ b/usr/src/uts/i86pc/io/vmm/io/vatpit.h
@@ -42,4 +42,8 @@ int vatpit_handler(struct vm *vm, int vcpuid, bool in, int port, int bytes,
int vatpit_nmisc_handler(struct vm *vm, int vcpuid, bool in, int port,
int bytes, uint32_t *eax);
+#ifndef __FreeBSD__
+void vatpit_localize_resources(struct vatpit *);
+#endif
+
#endif /* _VATPIT_H_ */
diff --git a/usr/src/uts/i86pc/io/vmm/vmm.c b/usr/src/uts/i86pc/io/vmm/vmm.c
index 13a23dfc85..02adf82fca 100644
--- a/usr/src/uts/i86pc/io/vmm/vmm.c
+++ b/usr/src/uts/i86pc/io/vmm/vmm.c
@@ -1888,6 +1888,7 @@ vm_localize_resources(struct vm *vm, struct vcpu *vcpu)
if (vcpu == &vm->vcpu[0]) {
vhpet_localize_resources(vm->vhpet);
vrtc_localize_resources(vm->vrtc);
+ vatpit_localize_resources(vm->vatpit);
}
vlapic_localize_resources(vcpu->vlapic);