Changeset View
Changeset View
Standalone View
Standalone View
head/sys/amd64/vmm/vmm.c
Show First 20 Lines • Show All 146 Lines • ▼ Show 20 Lines | struct vm { | ||||
void *iommu; /* (x) iommu-specific data */ | void *iommu; /* (x) iommu-specific data */ | ||||
struct vhpet *vhpet; /* (i) virtual HPET */ | struct vhpet *vhpet; /* (i) virtual HPET */ | ||||
struct vioapic *vioapic; /* (i) virtual ioapic */ | struct vioapic *vioapic; /* (i) virtual ioapic */ | ||||
struct vatpic *vatpic; /* (i) virtual atpic */ | struct vatpic *vatpic; /* (i) virtual atpic */ | ||||
struct vatpit *vatpit; /* (i) virtual atpit */ | struct vatpit *vatpit; /* (i) virtual atpit */ | ||||
struct vpmtmr *vpmtmr; /* (i) virtual ACPI PM timer */ | struct vpmtmr *vpmtmr; /* (i) virtual ACPI PM timer */ | ||||
struct vrtc *vrtc; /* (o) virtual RTC */ | struct vrtc *vrtc; /* (o) virtual RTC */ | ||||
volatile cpuset_t active_cpus; /* (i) active vcpus */ | volatile cpuset_t active_cpus; /* (i) active vcpus */ | ||||
volatile cpuset_t debug_cpus; /* (i) vcpus stopped for debug */ | |||||
int suspend; /* (i) stop VM execution */ | int suspend; /* (i) stop VM execution */ | ||||
volatile cpuset_t suspended_cpus; /* (i) suspended vcpus */ | volatile cpuset_t suspended_cpus; /* (i) suspended vcpus */ | ||||
volatile cpuset_t halted_cpus; /* (x) cpus in a hard halt */ | volatile cpuset_t halted_cpus; /* (x) cpus in a hard halt */ | ||||
cpuset_t rendezvous_req_cpus; /* (x) rendezvous requested */ | cpuset_t rendezvous_req_cpus; /* (x) rendezvous requested */ | ||||
cpuset_t rendezvous_done_cpus; /* (x) rendezvous finished */ | cpuset_t rendezvous_done_cpus; /* (x) rendezvous finished */ | ||||
void *rendezvous_arg; /* (x) rendezvous func/arg */ | void *rendezvous_arg; /* (x) rendezvous func/arg */ | ||||
vm_rendezvous_func_t rendezvous_func; | vm_rendezvous_func_t rendezvous_func; | ||||
struct mtx rendezvous_mtx; /* (o) rendezvous lock */ | struct mtx rendezvous_mtx; /* (o) rendezvous lock */ | ||||
▲ Show 20 Lines • Show All 247 Lines • ▼ Show 20 Lines | vm_init(struct vm *vm, bool create) | ||||
vm->vhpet = vhpet_init(vm); | vm->vhpet = vhpet_init(vm); | ||||
vm->vatpic = vatpic_init(vm); | vm->vatpic = vatpic_init(vm); | ||||
vm->vatpit = vatpit_init(vm); | vm->vatpit = vatpit_init(vm); | ||||
vm->vpmtmr = vpmtmr_init(vm); | vm->vpmtmr = vpmtmr_init(vm); | ||||
if (create) | if (create) | ||||
vm->vrtc = vrtc_init(vm); | vm->vrtc = vrtc_init(vm); | ||||
CPU_ZERO(&vm->active_cpus); | CPU_ZERO(&vm->active_cpus); | ||||
CPU_ZERO(&vm->debug_cpus); | |||||
vm->suspend = 0; | vm->suspend = 0; | ||||
CPU_ZERO(&vm->suspended_cpus); | CPU_ZERO(&vm->suspended_cpus); | ||||
for (i = 0; i < VM_MAXCPU; i++) | for (i = 0; i < VM_MAXCPU; i++) | ||||
vcpu_init(vm, i, create); | vcpu_init(vm, i, create); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 852 Lines • ▼ Show 20 Lines | if (!intr_disabled) { | ||||
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(vm, vcpuid)) | ||||
break; | break; | ||||
if (vcpu_debugged(vm, vcpuid)) | |||||
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. | ||||
*/ | */ | ||||
if (intr_disabled) { | if (intr_disabled) { | ||||
wmesg = "vmhalt"; | wmesg = "vmhalt"; | ||||
▲ Show 20 Lines • Show All 255 Lines • ▼ Show 20 Lines | vm_exit_suspended(struct vm *vm, int vcpuid, uint64_t rip) | ||||
vmexit = vm_exitinfo(vm, vcpuid); | vmexit = vm_exitinfo(vm, vcpuid); | ||||
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) | |||||
{ | |||||
struct vm_exit *vmexit; | |||||
vmexit = vm_exitinfo(vm, vcpuid); | |||||
vmexit->rip = rip; | |||||
vmexit->inst_length = 0; | |||||
vmexit->exitcode = VM_EXITCODE_DEBUG; | |||||
} | |||||
void | |||||
vm_exit_rendezvous(struct vm *vm, int vcpuid, uint64_t rip) | vm_exit_rendezvous(struct vm *vm, int vcpuid, uint64_t rip) | ||||
{ | { | ||||
struct vm_exit *vmexit; | struct vm_exit *vmexit; | ||||
KASSERT(vm->rendezvous_func != NULL, ("rendezvous not in progress")); | KASSERT(vm->rendezvous_func != NULL, ("rendezvous not in progress")); | ||||
vmexit = vm_exitinfo(vm, vcpuid); | vmexit = vm_exitinfo(vm, vcpuid); | ||||
vmexit->rip = rip; | vmexit->rip = rip; | ||||
▲ Show 20 Lines • Show All 697 Lines • ▼ Show 20 Lines | vm_activate_cpu(struct vm *vm, int vcpuid) | ||||
if (CPU_ISSET(vcpuid, &vm->active_cpus)) | if (CPU_ISSET(vcpuid, &vm->active_cpus)) | ||||
return (EBUSY); | return (EBUSY); | ||||
VCPU_CTR0(vm, vcpuid, "activated"); | VCPU_CTR0(vm, vcpuid, "activated"); | ||||
CPU_SET_ATOMIC(vcpuid, &vm->active_cpus); | CPU_SET_ATOMIC(vcpuid, &vm->active_cpus); | ||||
return (0); | return (0); | ||||
} | } | ||||
int | |||||
vm_suspend_cpu(struct vm *vm, int vcpuid) | |||||
{ | |||||
int i; | |||||
if (vcpuid < -1 || vcpuid >= VM_MAXCPU) | |||||
return (EINVAL); | |||||
if (vcpuid == -1) { | |||||
vm->debug_cpus = vm->active_cpus; | |||||
for (i = 0; i < VM_MAXCPU; i++) { | |||||
if (CPU_ISSET(i, &vm->active_cpus)) | |||||
vcpu_notify_event(vm, i, false); | |||||
} | |||||
} else { | |||||
if (!CPU_ISSET(vcpuid, &vm->active_cpus)) | |||||
return (EINVAL); | |||||
CPU_SET_ATOMIC(vcpuid, &vm->debug_cpus); | |||||
vcpu_notify_event(vm, vcpuid, false); | |||||
} | |||||
return (0); | |||||
} | |||||
int | |||||
vm_resume_cpu(struct vm *vm, int vcpuid) | |||||
{ | |||||
if (vcpuid < -1 || vcpuid >= VM_MAXCPU) | |||||
return (EINVAL); | |||||
if (vcpuid == -1) { | |||||
CPU_ZERO(&vm->debug_cpus); | |||||
} else { | |||||
if (!CPU_ISSET(vcpuid, &vm->debug_cpus)) | |||||
return (EINVAL); | |||||
CPU_CLR_ATOMIC(vcpuid, &vm->debug_cpus); | |||||
} | |||||
return (0); | |||||
} | |||||
int | |||||
vcpu_debugged(struct vm *vm, int vcpuid) | |||||
{ | |||||
return (CPU_ISSET(vcpuid, &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); | ||||
} | |||||
cpuset_t | |||||
vm_debug_cpus(struct vm *vm) | |||||
{ | |||||
return (vm->debug_cpus); | |||||
} | } | ||||
cpuset_t | cpuset_t | ||||
vm_suspended_cpus(struct vm *vm) | vm_suspended_cpus(struct vm *vm) | ||||
{ | { | ||||
return (vm->suspended_cpus); | return (vm->suspended_cpus); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 312 Lines • Show Last 20 Lines |