Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/vmm/io/vlapic.c
Show All 26 Lines | |||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
* | * | ||||
* $FreeBSD$ | * $FreeBSD$ | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include "opt_bhyve_snapshot.h" | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/smp.h> | #include <sys/smp.h> | ||||
#include <x86/specialreg.h> | #include <x86/specialreg.h> | ||||
#include <x86/apicreg.h> | #include <x86/apicreg.h> | ||||
#include <machine/clock.h> | #include <machine/clock.h> | ||||
#include <machine/smp.h> | #include <machine/smp.h> | ||||
#include <machine/vmm.h> | #include <machine/vmm.h> | ||||
#include <machine/vmm_snapshot.h> | |||||
#include "vmm_lapic.h" | #include "vmm_lapic.h" | ||||
#include "vmm_ktr.h" | #include "vmm_ktr.h" | ||||
#include "vmm_stat.h" | #include "vmm_stat.h" | ||||
#include "vlapic.h" | #include "vlapic.h" | ||||
#include "vlapic_priv.h" | #include "vlapic_priv.h" | ||||
#include "vioapic.h" | #include "vioapic.h" | ||||
▲ Show 20 Lines • Show All 1,587 Lines • ▼ Show 20 Lines | vlapic_set_tmr_level(struct vlapic *vlapic, uint32_t dest, bool phys, | ||||
vlapic_calcdest(vlapic->vm, &dmask, dest, phys, lowprio, false); | vlapic_calcdest(vlapic->vm, &dmask, dest, phys, lowprio, false); | ||||
if (!CPU_ISSET(vlapic->vcpuid, &dmask)) | if (!CPU_ISSET(vlapic->vcpuid, &dmask)) | ||||
return; | return; | ||||
VLAPIC_CTR1(vlapic, "vector %d set to level-triggered", vector); | VLAPIC_CTR1(vlapic, "vector %d set to level-triggered", vector); | ||||
vlapic_set_tmr(vlapic, vector, true); | vlapic_set_tmr(vlapic, vector, true); | ||||
} | } | ||||
#ifdef BHYVE_SNAPSHOT | |||||
static void | |||||
vlapic_reset_callout(struct vlapic *vlapic, uint32_t ccr) | |||||
{ | |||||
/* The implementation is similar to the one in the | |||||
pmooney_pfmooney.com: Why was this accessor added? | |||||
Done Inline ActionsRemoved it; was a leftover from an older implementation. darius.mihaim_gmail.com: Removed it; was a leftover from an older implementation. | |||||
* `vlapic_icrtmr_write_handler` function | |||||
*/ | |||||
sbintime_t sbt; | |||||
struct bintime bt; | |||||
VLAPIC_TIMER_LOCK(vlapic); | |||||
bt = vlapic->timer_freq_bt; | |||||
bintime_mul(&bt, ccr); | |||||
if (ccr != 0) { | |||||
binuptime(&vlapic->timer_fire_bt); | |||||
bintime_add(&vlapic->timer_fire_bt, &bt); | |||||
sbt = bttosbt(bt); | |||||
callout_reset_sbt(&vlapic->callout, sbt, 0, | |||||
vlapic_callout_handler, vlapic, 0); | |||||
} else { | |||||
/* even if the CCR was 0, periodic timers should be reset */ | |||||
if (vlapic_periodic_timer(vlapic)) { | |||||
binuptime(&vlapic->timer_fire_bt); | |||||
bintime_add(&vlapic->timer_fire_bt, | |||||
&vlapic->timer_period_bt); | |||||
sbt = bttosbt(vlapic->timer_period_bt); | |||||
callout_stop(&vlapic->callout); | |||||
callout_reset_sbt(&vlapic->callout, sbt, 0, | |||||
vlapic_callout_handler, vlapic, 0); | |||||
} | |||||
} | |||||
VLAPIC_TIMER_UNLOCK(vlapic); | |||||
} | |||||
int | |||||
vlapic_snapshot(struct vm *vm, struct vm_snapshot_meta *meta) | |||||
{ | |||||
int i, ret; | |||||
struct vlapic *vlapic; | |||||
struct LAPIC *lapic; | |||||
uint32_t ccr; | |||||
KASSERT(vm != NULL, ("%s: arg was NULL", __func__)); | |||||
ret = 0; | |||||
for (i = 0; i < VM_MAXCPU; i++) { | |||||
vlapic = vm_lapic(vm, i); | |||||
/* snapshot the page first; timer period depends on icr_timer */ | |||||
lapic = vlapic->apic_page; | |||||
SNAPSHOT_BUF_OR_LEAVE(lapic, PAGE_SIZE, meta, ret, done); | |||||
SNAPSHOT_VAR_OR_LEAVE(vlapic->esr_pending, meta, ret, done); | |||||
SNAPSHOT_VAR_OR_LEAVE(vlapic->timer_freq_bt.sec, | |||||
meta, ret, done); | |||||
SNAPSHOT_VAR_OR_LEAVE(vlapic->timer_freq_bt.frac, | |||||
meta, ret, done); | |||||
/* | |||||
* Timer period is equal to 'icr_timer' ticks at a frequency of | |||||
* 'timer_freq_bt'. | |||||
*/ | |||||
if (meta->op == VM_SNAPSHOT_RESTORE) { | |||||
vlapic->timer_period_bt = vlapic->timer_freq_bt; | |||||
bintime_mul(&vlapic->timer_period_bt, lapic->icr_timer); | |||||
} | |||||
SNAPSHOT_BUF_OR_LEAVE(vlapic->isrvec_stk, | |||||
sizeof(vlapic->isrvec_stk), | |||||
meta, ret, done); | |||||
SNAPSHOT_VAR_OR_LEAVE(vlapic->isrvec_stk_top, meta, ret, done); | |||||
SNAPSHOT_VAR_OR_LEAVE(vlapic->boot_state, meta, ret, done); | |||||
SNAPSHOT_BUF_OR_LEAVE(vlapic->lvt_last, | |||||
sizeof(vlapic->lvt_last), | |||||
meta, ret, done); | |||||
if (meta->op == VM_SNAPSHOT_SAVE) | |||||
ccr = vlapic_get_ccr(vlapic); | |||||
SNAPSHOT_VAR_OR_LEAVE(ccr, meta, ret, done); | |||||
if (meta->op == VM_SNAPSHOT_RESTORE) { | |||||
/* Reset the value of the 'timer_fire_bt' and the vlapic | |||||
* callout based on the value of the current count | |||||
* register saved when the VM snapshot was created | |||||
*/ | |||||
vlapic_reset_callout(vlapic, ccr); | |||||
} | |||||
} | |||||
done: | |||||
return (ret); | |||||
} | |||||
#endif |
Why was this accessor added?