diff options
author | Patrick Mooney <pmooney@pfmooney.com> | 2018-04-25 20:05:05 +0000 |
---|---|---|
committer | Patrick Mooney <pmooney@pfmooney.com> | 2018-06-19 14:53:28 +0000 |
commit | 4f723dcffd015c7d11cd1c7a3155f46aa0600646 (patch) | |
tree | ad36a6135b2ce9020ad402cc19f844306801cd9c | |
parent | 967bcd4bf4ed12e06a616379429f6f1a8765bbe4 (diff) | |
download | illumos-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.h | 10 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/io/vatpit.c | 82 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/io/vatpit.h | 4 | ||||
-rw-r--r-- | usr/src/uts/i86pc/io/vmm/vmm.c | 1 |
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); |