Skip to content

Commit

Permalink
BHYVE: OS-6923 bhyve could be more precise with vPIT
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
pfmooney authored and hadfl committed Jul 6, 2018
1 parent 4c85d1e commit df15441
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 26 deletions.
10 changes: 10 additions & 0 deletions usr/src/compat/freebsd/sys/time.h
Expand Up @@ -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)
{
Expand Down
82 changes: 56 additions & 26 deletions 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.
Expand Down Expand Up @@ -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 */
Expand All @@ -87,34 +88,49 @@ 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;
};

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;
Expand Down Expand Up @@ -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);
}
Expand All @@ -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)
Expand All @@ -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) {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -423,7 +442,6 @@ struct vatpit *
vatpit_init(struct vm *vm)
{
struct vatpit *vatpit;
struct bintime bt;
struct vatpit_callout_arg *arg;
int i;

Expand All @@ -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);
Expand All @@ -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 */
4 changes: 4 additions & 0 deletions usr/src/uts/i86pc/io/vmm/io/vatpit.h
Expand Up @@ -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_ */
1 change: 1 addition & 0 deletions usr/src/uts/i86pc/io/vmm/vmm.c
Expand Up @@ -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);
Expand Down

0 comments on commit df15441

Please sign in to comment.