Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/vmm/io/vhpet.c
Show All 37 Lines | |||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <dev/acpica/acpi_hpet.h> | #include <dev/acpica/acpi_hpet.h> | ||||
#include <machine/vmm.h> | #include <machine/vmm.h> | ||||
#include <machine/vmm_dev.h> | #include <machine/vmm_dev.h> | ||||
#include <machine/vmm_snapshot.h> | |||||
#include "vmm_lapic.h" | #include "vmm_lapic.h" | ||||
#include "vatpic.h" | #include "vatpic.h" | ||||
#include "vioapic.h" | #include "vioapic.h" | ||||
#include "vhpet.h" | #include "vhpet.h" | ||||
#include "vmm_ktr.h" | #include "vmm_ktr.h" | ||||
▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | |||||
static uint32_t | static uint32_t | ||||
vhpet_counter(struct vhpet *vhpet, sbintime_t *nowptr) | vhpet_counter(struct vhpet *vhpet, sbintime_t *nowptr) | ||||
{ | { | ||||
uint32_t val; | uint32_t val; | ||||
sbintime_t now, delta; | sbintime_t now, delta; | ||||
val = vhpet->countbase; | val = vhpet->countbase; | ||||
/* Since the countbase can be set by the guest at any point, we cannot | |||||
* directly set it during snapshot/restore because it can be | |||||
* overwritten. | |||||
*/ | |||||
if (vhpet_counter_enabled(vhpet)) { | if (vhpet_counter_enabled(vhpet)) { | ||||
now = sbinuptime(); | now = sbinuptime(); | ||||
delta = now - vhpet->countbase_sbt; | delta = now - vhpet->countbase_sbt; | ||||
KASSERT(delta >= 0, ("vhpet_counter: uptime went backwards: " | KASSERT(delta >= 0, ("vhpet_counter: uptime went backwards: " | ||||
"%#lx to %#lx", vhpet->countbase_sbt, now)); | "%#lx to %#lx", vhpet->countbase_sbt, now)); | ||||
val += delta / vhpet->freq_sbt; | val += delta / vhpet->freq_sbt; | ||||
if (nowptr != NULL) | if (nowptr != NULL) | ||||
*nowptr = now; | *nowptr = now; | ||||
▲ Show 20 Lines • Show All 199 Lines • ▼ Show 20 Lines | vhpet_start_counting(struct vhpet *vhpet) | ||||
int i; | int i; | ||||
vhpet->countbase_sbt = sbinuptime(); | vhpet->countbase_sbt = sbinuptime(); | ||||
for (i = 0; i < VHPET_NUM_TIMERS; i++) { | for (i = 0; i < VHPET_NUM_TIMERS; i++) { | ||||
/* | /* | ||||
* Restart the timers based on the value of the main counter | * Restart the timers based on the value of the main counter | ||||
* when it stopped counting. | * when it stopped counting. | ||||
*/ | */ | ||||
vhpet_start_timer(vhpet, i, vhpet->countbase, | vhpet_start_timer(vhpet, i, | ||||
vhpet->countbase_sbt); | vhpet->countbase, vhpet->countbase_sbt); | ||||
} | } | ||||
} | } | ||||
static void | static void | ||||
vhpet_stop_counting(struct vhpet *vhpet, uint32_t counter, sbintime_t now) | vhpet_stop_counting(struct vhpet *vhpet, uint32_t counter, sbintime_t now) | ||||
{ | { | ||||
int i; | int i; | ||||
▲ Show 20 Lines • Show All 373 Lines • ▼ Show 20 Lines | vhpet_cleanup(struct vhpet *vhpet) | ||||
free(vhpet, M_VHPET); | free(vhpet, M_VHPET); | ||||
} | } | ||||
int | int | ||||
vhpet_getcap(struct vm_hpet_cap *cap) | vhpet_getcap(struct vm_hpet_cap *cap) | ||||
{ | { | ||||
cap->capabilities = vhpet_capabilities(); | cap->capabilities = vhpet_capabilities(); | ||||
return (0); | |||||
} | |||||
int | |||||
vhpet_snapshot(struct vhpet *vhpet, struct vm_snapshot_meta *meta) | |||||
{ | |||||
int i, ret; | |||||
uint32_t countbase; | |||||
SNAPSHOT_VAR_OR_LEAVE(vhpet->freq_sbt, meta, ret, done); | |||||
SNAPSHOT_VAR_OR_LEAVE(vhpet->config, meta, ret, done); | |||||
SNAPSHOT_VAR_OR_LEAVE(vhpet->isr, meta, ret, done); | |||||
/* at restore time the countbase should have the value it had when the | |||||
* snapshot was created; since the value is not directly kept in | |||||
* vhpet->countbase, but rather computed relative to the current system | |||||
* uptime using countbase_sbt, save the value retured by vhpet_counter | |||||
*/ | |||||
if (meta->op == VM_SNAPSHOT_SAVE) | |||||
countbase = vhpet_counter(vhpet, NULL); | |||||
SNAPSHOT_VAR_OR_LEAVE(countbase, meta, ret, done); | |||||
if (meta->op == VM_SNAPSHOT_RESTORE) | |||||
vhpet->countbase = countbase; | |||||
for (i = 0; i < nitems(vhpet->timer); i++) { | |||||
SNAPSHOT_VAR_OR_LEAVE(vhpet->timer[i].cap_config, | |||||
meta, ret, done); | |||||
SNAPSHOT_VAR_OR_LEAVE(vhpet->timer[i].msireg, meta, ret, done); | |||||
SNAPSHOT_VAR_OR_LEAVE(vhpet->timer[i].compval, meta, ret, done); | |||||
SNAPSHOT_VAR_OR_LEAVE(vhpet->timer[i].comprate, meta, ret, done); | |||||
SNAPSHOT_VAR_OR_LEAVE(vhpet->timer[i].callout_sbt, | |||||
meta, ret, done); | |||||
} | |||||
done: | |||||
return (ret); | |||||
} | |||||
int | |||||
vhpet_restore_time(struct vhpet *vhpet) | |||||
{ | |||||
if (vhpet_counter_enabled(vhpet)) | |||||
vhpet_start_counting(vhpet); | |||||
return (0); | return (0); | ||||
} | } |