Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/vmm/vmm.c
Show First 20 Lines • Show All 360 Lines • ▼ Show 20 Lines | vcpu_init(struct vm *vm, int vcpu_id, bool create) | ||||
vcpu->extint_pending = 0; | vcpu->extint_pending = 0; | ||||
vcpu->exception_pending = 0; | vcpu->exception_pending = 0; | ||||
vcpu->guest_xcr0 = XFEATURE_ENABLED_X87; | vcpu->guest_xcr0 = XFEATURE_ENABLED_X87; | ||||
fpu_save_area_reset(vcpu->guestfpu); | fpu_save_area_reset(vcpu->guestfpu); | ||||
vmm_stat_init(vcpu->stats); | vmm_stat_init(vcpu->stats); | ||||
} | } | ||||
int | int | ||||
vcpu_trace_exceptions(struct vm *vm, int vcpuid) | vcpu_trace_exceptions(struct vcpu *vcpu) | ||||
{ | { | ||||
return (trace_guest_exceptions); | return (trace_guest_exceptions); | ||||
} | } | ||||
int | int | ||||
vcpu_trap_wbinvd(struct vm *vm, int vcpuid) | vcpu_trap_wbinvd(struct vcpu *vcpu) | ||||
{ | { | ||||
return (trap_wbinvd); | return (trap_wbinvd); | ||||
} | } | ||||
struct vm_exit * | struct vm_exit * | ||||
vm_exitinfo(struct vm *vm, int cpuid) | vm_exitinfo(struct vcpu *vcpu) | ||||
{ | { | ||||
struct vcpu *vcpu; | |||||
if (cpuid < 0 || cpuid >= vm->maxcpus) | |||||
panic("vm_exitinfo: invalid cpuid %d", cpuid); | |||||
vcpu = &vm->vcpu[cpuid]; | |||||
return (&vcpu->exitinfo); | return (&vcpu->exitinfo); | ||||
} | } | ||||
static int | static int | ||||
vmm_init(void) | vmm_init(void) | ||||
{ | { | ||||
int error; | int error; | ||||
▲ Show 20 Lines • Show All 276 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* Return 'true' if 'gpa' is allocated in the guest address space. | * Return 'true' if 'gpa' is allocated in the guest address space. | ||||
* | * | ||||
* This function is called in the context of a running vcpu which acts as | * This function is called in the context of a running vcpu which acts as | ||||
* an implicit lock on 'vm->mem_maps[]'. | * an implicit lock on 'vm->mem_maps[]'. | ||||
*/ | */ | ||||
bool | bool | ||||
vm_mem_allocated(struct vm *vm, int vcpuid, vm_paddr_t gpa) | vm_mem_allocated(struct vcpu *vcpu, vm_paddr_t gpa) | ||||
{ | { | ||||
struct vm *vm = vcpu->vm; | |||||
struct mem_map *mm; | struct mem_map *mm; | ||||
int i; | int i; | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
int hostcpu, state; | int hostcpu, state; | ||||
state = vcpu_get_state(vm_vcpu(vm, vcpuid), &hostcpu); | state = vcpu_get_state(vcpu, &hostcpu); | ||||
KASSERT(state == VCPU_RUNNING && hostcpu == curcpu, | KASSERT(state == VCPU_RUNNING && hostcpu == curcpu, | ||||
("%s: invalid vcpu state %d/%d", __func__, state, hostcpu)); | ("%s: invalid vcpu state %d/%d", __func__, state, hostcpu)); | ||||
#endif | #endif | ||||
for (i = 0; i < VM_MAX_MEMMAPS; i++) { | for (i = 0; i < VM_MAX_MEMMAPS; i++) { | ||||
mm = &vm->mem_maps[i]; | mm = &vm->mem_maps[i]; | ||||
if (mm->len != 0 && gpa >= mm->gpa && gpa < mm->gpa + mm->len) | if (mm->len != 0 && gpa >= mm->gpa && gpa < mm->gpa + mm->len) | ||||
return (true); /* 'gpa' is sysmem or devmem */ | return (true); /* 'gpa' is sysmem or devmem */ | ||||
▲ Show 20 Lines • Show All 706 Lines • ▼ Show 20 Lines | while (1) { | ||||
* software events that would cause this vcpu to wakeup. | * software events that would cause this vcpu to wakeup. | ||||
* | * | ||||
* These interrupts/events could have happened after the | * These interrupts/events could have happened after the | ||||
* vcpu returned from vmmops_run() and before it acquired the | * vcpu returned from vmmops_run() and before it acquired the | ||||
* vcpu lock above. | * vcpu lock above. | ||||
*/ | */ | ||||
if (vm->rendezvous_func != NULL || vm->suspend || vcpu->reqidle) | if (vm->rendezvous_func != NULL || vm->suspend || vcpu->reqidle) | ||||
break; | break; | ||||
if (vm_nmi_pending(vm, vcpuid)) | if (vm_nmi_pending(vcpu)) | ||||
break; | break; | ||||
if (!intr_disabled) { | if (!intr_disabled) { | ||||
if (vm_extint_pending(vm, vcpuid) || | if (vm_extint_pending(vcpu) || | ||||
vlapic_pending_intr(vcpu->vlapic, NULL)) { | vlapic_pending_intr(vcpu->vlapic, NULL)) { | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
/* Don't go to sleep if the vcpu thread needs to yield */ | /* Don't go to sleep if the vcpu thread needs to yield */ | ||||
if (vcpu_should_yield(vm, vcpuid)) | if (vcpu_should_yield(vcpu)) | ||||
break; | break; | ||||
if (vcpu_debugged(vm, vcpuid)) | if (vcpu_debugged(vcpu)) | ||||
break; | break; | ||||
/* | /* | ||||
* Some Linux guests implement "halt" by having all vcpus | * Some Linux guests implement "halt" by having all vcpus | ||||
* execute HLT with interrupts disabled. 'halted_cpus' keeps | * execute HLT with interrupts disabled. 'halted_cpus' keeps | ||||
* track of the vcpus that have entered this state. When all | * track of the vcpus that have entered this state. When all | ||||
* vcpus enter the halted state the virtual machine is halted. | * vcpus enter the halted state the virtual machine is halted. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 261 Lines • ▼ Show 20 Lines | for (i = 0; i < vm->maxcpus; i++) { | ||||
if (CPU_ISSET(i, &vm->active_cpus)) | if (CPU_ISSET(i, &vm->active_cpus)) | ||||
vcpu_notify_event(vm, i, false); | vcpu_notify_event(vm, i, false); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
void | void | ||||
vm_exit_suspended(struct vm *vm, int vcpuid, uint64_t rip) | vm_exit_suspended(struct vcpu *vcpu, uint64_t rip) | ||||
{ | { | ||||
struct vm *vm = vcpu->vm; | |||||
struct vm_exit *vmexit; | struct vm_exit *vmexit; | ||||
KASSERT(vm->suspend > VM_SUSPEND_NONE && vm->suspend < VM_SUSPEND_LAST, | KASSERT(vm->suspend > VM_SUSPEND_NONE && vm->suspend < VM_SUSPEND_LAST, | ||||
("vm_exit_suspended: invalid suspend type %d", vm->suspend)); | ("vm_exit_suspended: invalid suspend type %d", vm->suspend)); | ||||
vmexit = vm_exitinfo(vm, vcpuid); | vmexit = vm_exitinfo(vcpu); | ||||
vmexit->rip = rip; | vmexit->rip = rip; | ||||
vmexit->inst_length = 0; | vmexit->inst_length = 0; | ||||
vmexit->exitcode = VM_EXITCODE_SUSPENDED; | vmexit->exitcode = VM_EXITCODE_SUSPENDED; | ||||
vmexit->u.suspended.how = vm->suspend; | vmexit->u.suspended.how = vm->suspend; | ||||
} | } | ||||
void | void | ||||
vm_exit_debug(struct vm *vm, int vcpuid, uint64_t rip) | vm_exit_debug(struct vcpu *vcpu, uint64_t rip) | ||||
{ | { | ||||
struct vm_exit *vmexit; | struct vm_exit *vmexit; | ||||
vmexit = vm_exitinfo(vm, vcpuid); | vmexit = vm_exitinfo(vcpu); | ||||
vmexit->rip = rip; | vmexit->rip = rip; | ||||
vmexit->inst_length = 0; | vmexit->inst_length = 0; | ||||
vmexit->exitcode = VM_EXITCODE_DEBUG; | vmexit->exitcode = VM_EXITCODE_DEBUG; | ||||
} | } | ||||
void | void | ||||
vm_exit_rendezvous(struct vm *vm, int vcpuid, uint64_t rip) | vm_exit_rendezvous(struct vcpu *vcpu, uint64_t rip) | ||||
{ | { | ||||
struct vm_exit *vmexit; | struct vm_exit *vmexit; | ||||
KASSERT(vm->rendezvous_func != NULL, ("rendezvous not in progress")); | KASSERT(vcpu->vm->rendezvous_func != NULL, | ||||
("rendezvous not in progress")); | |||||
vmexit = vm_exitinfo(vm, vcpuid); | vmexit = vm_exitinfo(vcpu); | ||||
vmexit->rip = rip; | vmexit->rip = rip; | ||||
vmexit->inst_length = 0; | vmexit->inst_length = 0; | ||||
vmexit->exitcode = VM_EXITCODE_RENDEZVOUS; | vmexit->exitcode = VM_EXITCODE_RENDEZVOUS; | ||||
vmm_stat_incr(vm_vcpu(vm, vcpuid), VMEXIT_RENDEZVOUS, 1); | vmm_stat_incr(vcpu, VMEXIT_RENDEZVOUS, 1); | ||||
} | } | ||||
void | void | ||||
vm_exit_reqidle(struct vm *vm, int vcpuid, uint64_t rip) | vm_exit_reqidle(struct vcpu *vcpu, uint64_t rip) | ||||
{ | { | ||||
struct vm_exit *vmexit; | struct vm_exit *vmexit; | ||||
vmexit = vm_exitinfo(vm, vcpuid); | vmexit = vm_exitinfo(vcpu); | ||||
vmexit->rip = rip; | vmexit->rip = rip; | ||||
vmexit->inst_length = 0; | vmexit->inst_length = 0; | ||||
vmexit->exitcode = VM_EXITCODE_REQIDLE; | vmexit->exitcode = VM_EXITCODE_REQIDLE; | ||||
vmm_stat_incr(vm_vcpu(vm, vcpuid), VMEXIT_REQIDLE, 1); | vmm_stat_incr(vcpu, VMEXIT_REQIDLE, 1); | ||||
} | } | ||||
void | void | ||||
vm_exit_astpending(struct vm *vm, int vcpuid, uint64_t rip) | vm_exit_astpending(struct vcpu *vcpu, uint64_t rip) | ||||
{ | { | ||||
struct vm_exit *vmexit; | struct vm_exit *vmexit; | ||||
vmexit = vm_exitinfo(vm, vcpuid); | vmexit = vm_exitinfo(vcpu); | ||||
vmexit->rip = rip; | vmexit->rip = rip; | ||||
vmexit->inst_length = 0; | vmexit->inst_length = 0; | ||||
vmexit->exitcode = VM_EXITCODE_BOGUS; | vmexit->exitcode = VM_EXITCODE_BOGUS; | ||||
vmm_stat_incr(vm_vcpu(vm, vcpuid), VMEXIT_ASTPENDING, 1); | vmm_stat_incr(vcpu, VMEXIT_ASTPENDING, 1); | ||||
} | } | ||||
int | int | ||||
vm_run(struct vm *vm, struct vm_run *vmrun) | vm_run(struct vm *vm, struct vm_run *vmrun) | ||||
{ | { | ||||
struct vm_eventinfo evinfo; | struct vm_eventinfo evinfo; | ||||
int error, vcpuid; | int error, vcpuid; | ||||
struct vcpu *vcpu; | struct vcpu *vcpu; | ||||
▲ Show 20 Lines • Show All 137 Lines • ▼ Show 20 Lines | if (state == VCPU_RUNNING) { | ||||
vcpu->nextrip = rip; | vcpu->nextrip = rip; | ||||
} else { | } else { | ||||
panic("%s: invalid state %d", __func__, state); | panic("%s: invalid state %d", __func__, state); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
vm_exit_intinfo(struct vm *vm, int vcpuid, uint64_t info) | vm_exit_intinfo(struct vcpu *vcpu, uint64_t info) | ||||
{ | { | ||||
struct vcpu *vcpu; | |||||
int type, vector; | int type, vector; | ||||
if (vcpuid < 0 || vcpuid >= vm->maxcpus) | |||||
return (EINVAL); | |||||
vcpu = &vm->vcpu[vcpuid]; | |||||
if (info & VM_INTINFO_VALID) { | if (info & VM_INTINFO_VALID) { | ||||
type = info & VM_INTINFO_TYPE; | type = info & VM_INTINFO_TYPE; | ||||
vector = info & 0xff; | vector = info & 0xff; | ||||
if (type == VM_INTINFO_NMI && vector != IDT_NMI) | if (type == VM_INTINFO_NMI && vector != IDT_NMI) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (type == VM_INTINFO_HWEXCEPTION && vector >= 32) | if (type == VM_INTINFO_HWEXCEPTION && vector >= 32) | ||||
return (EINVAL); | return (EINVAL); | ||||
if (info & VM_INTINFO_RSVD) | if (info & VM_INTINFO_RSVD) | ||||
return (EINVAL); | return (EINVAL); | ||||
} else { | } else { | ||||
info = 0; | info = 0; | ||||
} | } | ||||
VCPU_CTR2(vm, vcpuid, "%s: info1(%#lx)", __func__, info); | VMM_CTR2(vcpu, "%s: info1(%#lx)", __func__, info); | ||||
vcpu->exitintinfo = info; | vcpu->exitintinfo = info; | ||||
return (0); | return (0); | ||||
} | } | ||||
enum exc_class { | enum exc_class { | ||||
EXC_BENIGN, | EXC_BENIGN, | ||||
EXC_CONTRIBUTORY, | EXC_CONTRIBUTORY, | ||||
EXC_PAGEFAULT | EXC_PAGEFAULT | ||||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Lines | exception_class(uint64_t info) | ||||
case IDT_GP: | case IDT_GP: | ||||
return (EXC_CONTRIBUTORY); | return (EXC_CONTRIBUTORY); | ||||
default: | default: | ||||
return (EXC_BENIGN); | return (EXC_BENIGN); | ||||
} | } | ||||
} | } | ||||
static int | static int | ||||
nested_fault(struct vm *vm, int vcpuid, uint64_t info1, uint64_t info2, | nested_fault(struct vcpu *vcpu, uint64_t info1, uint64_t info2, | ||||
uint64_t *retinfo) | uint64_t *retinfo) | ||||
{ | { | ||||
enum exc_class exc1, exc2; | enum exc_class exc1, exc2; | ||||
int type1, vector1; | int type1, vector1; | ||||
KASSERT(info1 & VM_INTINFO_VALID, ("info1 %#lx is not valid", info1)); | KASSERT(info1 & VM_INTINFO_VALID, ("info1 %#lx is not valid", info1)); | ||||
KASSERT(info2 & VM_INTINFO_VALID, ("info2 %#lx is not valid", info2)); | KASSERT(info2 & VM_INTINFO_VALID, ("info2 %#lx is not valid", info2)); | ||||
/* | /* | ||||
* If an exception occurs while attempting to call the double-fault | * If an exception occurs while attempting to call the double-fault | ||||
* handler the processor enters shutdown mode (aka triple fault). | * handler the processor enters shutdown mode (aka triple fault). | ||||
*/ | */ | ||||
type1 = info1 & VM_INTINFO_TYPE; | type1 = info1 & VM_INTINFO_TYPE; | ||||
vector1 = info1 & 0xff; | vector1 = info1 & 0xff; | ||||
if (type1 == VM_INTINFO_HWEXCEPTION && vector1 == IDT_DF) { | if (type1 == VM_INTINFO_HWEXCEPTION && vector1 == IDT_DF) { | ||||
VCPU_CTR2(vm, vcpuid, "triple fault: info1(%#lx), info2(%#lx)", | VMM_CTR2(vcpu, "triple fault: info1(%#lx), info2(%#lx)", | ||||
info1, info2); | info1, info2); | ||||
vm_suspend(vm, VM_SUSPEND_TRIPLEFAULT); | vm_suspend(vcpu->vm, VM_SUSPEND_TRIPLEFAULT); | ||||
*retinfo = 0; | *retinfo = 0; | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* Table 6-5 "Conditions for Generating a Double Fault", Intel SDM, Vol3 | * Table 6-5 "Conditions for Generating a Double Fault", Intel SDM, Vol3 | ||||
*/ | */ | ||||
exc1 = exception_class(info1); | exc1 = exception_class(info1); | ||||
Show All 23 Lines | if (vcpu->exc_errcode_valid) { | ||||
info |= VM_INTINFO_DEL_ERRCODE; | info |= VM_INTINFO_DEL_ERRCODE; | ||||
info |= (uint64_t)vcpu->exc_errcode << 32; | info |= (uint64_t)vcpu->exc_errcode << 32; | ||||
} | } | ||||
} | } | ||||
return (info); | return (info); | ||||
} | } | ||||
int | int | ||||
vm_entry_intinfo(struct vm *vm, int vcpuid, uint64_t *retinfo) | vm_entry_intinfo(struct vcpu *vcpu, uint64_t *retinfo) | ||||
{ | { | ||||
struct vcpu *vcpu; | |||||
uint64_t info1, info2; | uint64_t info1, info2; | ||||
int valid; | int valid; | ||||
KASSERT(vcpuid >= 0 && | |||||
vcpuid < vm->maxcpus, ("invalid vcpu %d", vcpuid)); | |||||
vcpu = &vm->vcpu[vcpuid]; | |||||
info1 = vcpu->exitintinfo; | info1 = vcpu->exitintinfo; | ||||
vcpu->exitintinfo = 0; | vcpu->exitintinfo = 0; | ||||
info2 = 0; | info2 = 0; | ||||
if (vcpu->exception_pending) { | if (vcpu->exception_pending) { | ||||
info2 = vcpu_exception_intinfo(vcpu); | info2 = vcpu_exception_intinfo(vcpu); | ||||
vcpu->exception_pending = 0; | vcpu->exception_pending = 0; | ||||
VCPU_CTR2(vm, vcpuid, "Exception %d delivered: %#lx", | VMM_CTR2(vcpu, "Exception %d delivered: %#lx", | ||||
vcpu->exc_vector, info2); | vcpu->exc_vector, info2); | ||||
} | } | ||||
if ((info1 & VM_INTINFO_VALID) && (info2 & VM_INTINFO_VALID)) { | if ((info1 & VM_INTINFO_VALID) && (info2 & VM_INTINFO_VALID)) { | ||||
valid = nested_fault(vm, vcpuid, info1, info2, retinfo); | valid = nested_fault(vcpu, info1, info2, retinfo); | ||||
} else if (info1 & VM_INTINFO_VALID) { | } else if (info1 & VM_INTINFO_VALID) { | ||||
*retinfo = info1; | *retinfo = info1; | ||||
valid = 1; | valid = 1; | ||||
} else if (info2 & VM_INTINFO_VALID) { | } else if (info2 & VM_INTINFO_VALID) { | ||||
*retinfo = info2; | *retinfo = info2; | ||||
valid = 1; | valid = 1; | ||||
} else { | } else { | ||||
valid = 0; | valid = 0; | ||||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | vm_inject_nmi(struct vm *vm, int vcpuid) | ||||
vcpu = &vm->vcpu[vcpuid]; | vcpu = &vm->vcpu[vcpuid]; | ||||
vcpu->nmi_pending = 1; | vcpu->nmi_pending = 1; | ||||
vcpu_notify_event(vm, vcpuid, false); | vcpu_notify_event(vm, vcpuid, false); | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
vm_nmi_pending(struct vm *vm, int vcpuid) | vm_nmi_pending(struct vcpu *vcpu) | ||||
{ | { | ||||
struct vcpu *vcpu; | |||||
if (vcpuid < 0 || vcpuid >= vm->maxcpus) | |||||
panic("vm_nmi_pending: invalid vcpuid %d", vcpuid); | |||||
vcpu = &vm->vcpu[vcpuid]; | |||||
return (vcpu->nmi_pending); | return (vcpu->nmi_pending); | ||||
} | } | ||||
void | void | ||||
vm_nmi_clear(struct vm *vm, int vcpuid) | vm_nmi_clear(struct vcpu *vcpu) | ||||
{ | { | ||||
struct vcpu *vcpu; | |||||
if (vcpuid < 0 || vcpuid >= vm->maxcpus) | |||||
panic("vm_nmi_pending: invalid vcpuid %d", vcpuid); | |||||
vcpu = &vm->vcpu[vcpuid]; | |||||
if (vcpu->nmi_pending == 0) | if (vcpu->nmi_pending == 0) | ||||
panic("vm_nmi_clear: inconsistent nmi_pending state"); | panic("vm_nmi_clear: inconsistent nmi_pending state"); | ||||
vcpu->nmi_pending = 0; | vcpu->nmi_pending = 0; | ||||
vmm_stat_incr(vcpu, VCPU_NMI_COUNT, 1); | vmm_stat_incr(vcpu, VCPU_NMI_COUNT, 1); | ||||
} | } | ||||
static VMM_STAT(VCPU_EXTINT_COUNT, "number of ExtINTs delivered to vcpu"); | static VMM_STAT(VCPU_EXTINT_COUNT, "number of ExtINTs delivered to vcpu"); | ||||
Show All 9 Lines | vm_inject_extint(struct vm *vm, int vcpuid) | ||||
vcpu = &vm->vcpu[vcpuid]; | vcpu = &vm->vcpu[vcpuid]; | ||||
vcpu->extint_pending = 1; | vcpu->extint_pending = 1; | ||||
vcpu_notify_event(vm, vcpuid, false); | vcpu_notify_event(vm, vcpuid, false); | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
vm_extint_pending(struct vm *vm, int vcpuid) | vm_extint_pending(struct vcpu *vcpu) | ||||
{ | { | ||||
struct vcpu *vcpu; | |||||
if (vcpuid < 0 || vcpuid >= vm->maxcpus) | |||||
panic("vm_extint_pending: invalid vcpuid %d", vcpuid); | |||||
vcpu = &vm->vcpu[vcpuid]; | |||||
return (vcpu->extint_pending); | return (vcpu->extint_pending); | ||||
} | } | ||||
void | void | ||||
vm_extint_clear(struct vm *vm, int vcpuid) | vm_extint_clear(struct vcpu *vcpu) | ||||
{ | { | ||||
struct vcpu *vcpu; | |||||
if (vcpuid < 0 || vcpuid >= vm->maxcpus) | |||||
panic("vm_extint_pending: invalid vcpuid %d", vcpuid); | |||||
vcpu = &vm->vcpu[vcpuid]; | |||||
if (vcpu->extint_pending == 0) | if (vcpu->extint_pending == 0) | ||||
panic("vm_extint_clear: inconsistent extint_pending state"); | panic("vm_extint_clear: inconsistent extint_pending state"); | ||||
vcpu->extint_pending = 0; | vcpu->extint_pending = 0; | ||||
vmm_stat_incr(vcpu, VCPU_EXTINT_COUNT, 1); | vmm_stat_incr(vcpu, VCPU_EXTINT_COUNT, 1); | ||||
} | } | ||||
int | int | ||||
▲ Show 20 Lines • Show All 193 Lines • ▼ Show 20 Lines | if (!CPU_ISSET(vcpuid, &vm->debug_cpus)) | ||||
return (EINVAL); | return (EINVAL); | ||||
CPU_CLR_ATOMIC(vcpuid, &vm->debug_cpus); | CPU_CLR_ATOMIC(vcpuid, &vm->debug_cpus); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
vcpu_debugged(struct vm *vm, int vcpuid) | vcpu_debugged(struct vcpu *vcpu) | ||||
{ | { | ||||
return (CPU_ISSET(vcpuid, &vm->debug_cpus)); | return (CPU_ISSET(vcpu->vcpuid, &vcpu->vm->debug_cpus)); | ||||
} | } | ||||
cpuset_t | cpuset_t | ||||
vm_active_cpus(struct vm *vm) | vm_active_cpus(struct vm *vm) | ||||
{ | { | ||||
return (vm->active_cpus); | return (vm->active_cpus); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 443 Lines • ▼ Show 20 Lines | vm_snapshot_req(struct vm *vm, struct vm_snapshot_meta *meta) | ||||
default: | default: | ||||
printf("%s: failed to find the requested type %#x\n", | printf("%s: failed to find the requested type %#x\n", | ||||
__func__, meta->dev_req); | __func__, meta->dev_req); | ||||
ret = (EINVAL); | ret = (EINVAL); | ||||
} | } | ||||
return (ret); | return (ret); | ||||
} | } | ||||
int | void | ||||
vm_set_tsc_offset(struct vm *vm, int vcpuid, uint64_t offset) | vm_set_tsc_offset(struct vcpu *vcpu, uint64_t offset) | ||||
{ | { | ||||
struct vcpu *vcpu; | |||||
if (vcpuid < 0 || vcpuid >= vm_get_maxcpus(vm)) | |||||
return (EINVAL); | |||||
vcpu = &vm->vcpu[vcpuid]; | |||||
vcpu->tsc_offset = offset; | vcpu->tsc_offset = offset; | ||||
return (0); | |||||
} | } | ||||
int | int | ||||
vm_restore_time(struct vm *vm) | vm_restore_time(struct vm *vm) | ||||
{ | { | ||||
int error; | int error; | ||||
uint64_t now; | uint64_t now; | ||||
struct vcpu *vcpu; | struct vcpu *vcpu; | ||||
Show All 21 Lines |