diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -264,14 +264,14 @@ int vm_set_register(struct vcpu *vcpu, int reg, uint64_t val); int vm_get_seg_desc(struct vcpu *vcpu, int reg, struct seg_desc *ret_desc); -int vm_set_seg_desc(struct vm *vm, int vcpu, int reg, +int vm_set_seg_desc(struct vcpu *vcpu, int reg, struct seg_desc *desc); -int vm_run(struct vm *vm, struct vm_run *vmrun); +int vm_run(struct vcpu *vcpu, struct vm_exit *vme_user); int vm_suspend(struct vm *vm, enum vm_suspend_how how); -int vm_inject_nmi(struct vm *vm, int vcpu); +int vm_inject_nmi(struct vcpu *vcpu); int vm_nmi_pending(struct vcpu *vcpu); void vm_nmi_clear(struct vcpu *vcpu); -int vm_inject_extint(struct vm *vm, int vcpu); +int vm_inject_extint(struct vcpu *vcpu); int vm_extint_pending(struct vcpu *vcpu); void vm_extint_clear(struct vcpu *vcpu); int vcpu_vcpuid(struct vcpu *vcpu); @@ -280,14 +280,14 @@ struct vlapic *vm_lapic(struct vcpu *vcpu); struct vioapic *vm_ioapic(struct vm *vm); struct vhpet *vm_hpet(struct vm *vm); -int vm_get_capability(struct vm *vm, int vcpu, int type, int *val); -int vm_set_capability(struct vm *vm, int vcpu, int type, int val); -int vm_get_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state *state); -int vm_set_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state state); +int vm_get_capability(struct vcpu *vcpu, int type, int *val); +int vm_set_capability(struct vcpu *vcpu, int type, int val); +int vm_get_x2apic_state(struct vcpu *vcpu, enum x2apic_state *state); +int vm_set_x2apic_state(struct vcpu *vcpu, enum x2apic_state state); int vm_apicid2vcpuid(struct vm *vm, int apicid); -int vm_activate_cpu(struct vm *vm, int vcpu); -int vm_suspend_cpu(struct vm *vm, int vcpu); -int vm_resume_cpu(struct vm *vm, int vcpu); +int vm_activate_cpu(struct vcpu *vcpu); +int vm_suspend_cpu(struct vm *vm, struct vcpu *vcpu); +int vm_resume_cpu(struct vm *vm, struct vcpu *vcpu); int vm_restart_instruction(struct vcpu *vcpu); struct vm_exit *vm_exitinfo(struct vcpu *vcpu); void vm_exit_suspended(struct vcpu *vcpu, uint64_t rip); @@ -361,8 +361,7 @@ VCPU_SLEEPING, }; -int vcpu_set_state(struct vm *vm, int vcpu, enum vcpu_state state, - bool from_idle); +int vcpu_set_state(struct vcpu *vcpu, enum vcpu_state state, bool from_idle); enum vcpu_state vcpu_get_state(struct vcpu *vcpu, int *hostcpu); static int __inline @@ -383,7 +382,7 @@ #endif void *vcpu_stats(struct vcpu *vcpu); -void vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr); +void vcpu_notify_event(struct vcpu *vcpu, bool lapic_intr); struct vmspace *vm_get_vmspace(struct vm *vm); struct vatpic *vm_atpic(struct vm *vm); struct vatpit *vm_atpit(struct vm *vm); @@ -429,7 +428,7 @@ */ int vm_entry_intinfo(struct vcpu *vcpu, uint64_t *info); -int vm_get_intinfo(struct vm *vm, int vcpuid, uint64_t *info1, uint64_t *info2); +int vm_get_intinfo(struct vcpu *vcpu, uint64_t *info1, uint64_t *info2); /* * Function used to keep track of the guest's TSC offset. The diff --git a/sys/amd64/vmm/io/vatpic.c b/sys/amd64/vmm/io/vatpic.c --- a/sys/amd64/vmm/io/vatpic.c +++ b/sys/amd64/vmm/io/vatpic.c @@ -262,7 +262,7 @@ * interrupt. */ atpic->intr_raised = true; - lapic_set_local_intr(vatpic->vm, -1, APIC_LVT_LINT0); + lapic_set_local_intr(vatpic->vm, NULL, APIC_LVT_LINT0); vioapic_pulse_irq(vatpic->vm, 0); } else { VATPIC_CTR3(vatpic, "atpic master no eligible interrupts " diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c --- a/sys/amd64/vmm/io/vlapic.c +++ b/sys/amd64/vmm/io/vlapic.c @@ -460,13 +460,13 @@ return (0); } if (vlapic_set_intr_ready(vlapic, vec, false)) - vcpu_notify_event(vlapic->vm, vlapic->vcpuid, true); + vcpu_notify_event(vlapic->vcpu, true); break; case APIC_LVT_DM_NMI: - vm_inject_nmi(vlapic->vm, vlapic->vcpuid); + vm_inject_nmi(vlapic->vcpu); break; case APIC_LVT_DM_EXTINT: - vm_inject_extint(vlapic->vm, vlapic->vcpuid); + vm_inject_extint(vlapic->vcpu); break; default: // Other modes ignored @@ -680,10 +680,10 @@ */ switch (vector) { case APIC_LVT_LINT0: - vm_inject_extint(vlapic->vm, vlapic->vcpuid); + vm_inject_extint(vlapic->vcpu); break; case APIC_LVT_LINT1: - vm_inject_nmi(vlapic->vm, vlapic->vcpuid); + vm_inject_nmi(vlapic->vcpu); break; default: break; @@ -1040,6 +1040,7 @@ uint64_t icrval; uint32_t dest, vec, mode, shorthand; struct vlapic *vlapic2; + struct vcpu *vcpu; struct vm_exit *vmexit; struct LAPIC *lapic; @@ -1100,7 +1101,8 @@ } CPU_FOREACH_ISSET(i, &dmask) { - lapic_intr_edge(vlapic->vm, i, vec); + vcpu = vm_vcpu(vlapic->vm, i); + lapic_intr_edge(vcpu, vec); vmm_stat_array_incr(vlapic->vcpu, IPIS_SENT, i, 1); VLAPIC_CTR2(vlapic, "vlapic sending ipi %d to vcpuid %d", vec, i); @@ -1109,7 +1111,8 @@ break; case APIC_DELMODE_NMI: CPU_FOREACH_ISSET(i, &dmask) { - vm_inject_nmi(vlapic->vm, i); + vcpu = vm_vcpu(vlapic->vm, i); + vm_inject_nmi(vcpu); VLAPIC_CTR1(vlapic, "vlapic sending ipi nmi to vcpuid %d", i); } @@ -1130,7 +1133,8 @@ * requires that the boot state is set to SIPI * here. */ - vlapic2 = vm_lapic(vm_vcpu(vlapic->vm, i)); + vcpu = vm_vcpu(vlapic->vm, i); + vlapic2 = vm_lapic(vcpu); vlapic2->boot_state = BS_SIPI; break; } @@ -1154,7 +1158,8 @@ /* * Ignore SIPIs in any state other than wait-for-SIPI */ - vlapic2 = vm_lapic(vm_vcpu(vlapic->vm, i)); + vcpu = vm_vcpu(vlapic->vm, i); + vlapic2 = vm_lapic(vcpu); if (vlapic2->boot_state != BS_SIPI) break; vlapic2->boot_state = BS_RUNNING; @@ -1169,7 +1174,8 @@ } CPU_FOREACH_ISSET(i, &dmask) { - vlapic2 = vm_lapic(vm_vcpu(vlapic->vm, i)); + vcpu = vm_vcpu(vlapic->vm, i); + vlapic2 = vm_lapic(vcpu); /* * Ignore SIPIs in any state other than wait-for-SIPI @@ -1235,7 +1241,7 @@ KASSERT(x2apic(vlapic), ("SELF_IPI does not exist in xAPIC mode")); vec = val & 0xff; - lapic_intr_edge(vlapic->vm, vlapic->vcpuid, vec); + lapic_intr_edge(vlapic->vcpu, vec); vmm_stat_array_incr(vlapic->vcpu, IPIS_SENT, vlapic->vcpuid, 1); VLAPIC_CTR1(vlapic, "vlapic self-ipi %d", vec); } @@ -1696,6 +1702,7 @@ vlapic_deliver_intr(struct vm *vm, bool level, uint32_t dest, bool phys, int delmode, int vec) { + struct vcpu *vcpu; bool lowprio; int vcpuid; cpuset_t dmask; @@ -1716,10 +1723,11 @@ vlapic_calcdest(vm, &dmask, dest, phys, lowprio, false); CPU_FOREACH_ISSET(vcpuid, &dmask) { + vcpu = vm_vcpu(vm, vcpuid); if (delmode == IOART_DELEXINT) { - vm_inject_extint(vm, vcpuid); + vm_inject_extint(vcpu); } else { - lapic_set_intr(vm, vcpuid, vec, level); + lapic_set_intr(vcpu, vec, level); } } } diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -309,12 +309,6 @@ } #endif -static __inline void * -vcpu_cookie(struct vm *vm, int i) -{ - return (vm->vcpu[i].cookie); -} - static void vcpu_cleanup(struct vm *vm, int i, bool destroy) { @@ -354,7 +348,7 @@ vcpu->cookie = vmmops_vcpu_init(vm->cookie, vcpu, vcpu_id); vcpu->vlapic = vmmops_vlapic_init(vcpu->cookie); - vm_set_x2apic_state(vm, vcpu_id, X2APIC_DISABLED); + vm_set_x2apic_state(vcpu, X2APIC_DISABLED); vcpu->reqidle = 0; vcpu->exitintinfo = 0; vcpu->nmi_pending = 0; @@ -1172,16 +1166,13 @@ } int -vm_set_seg_desc(struct vm *vm, int vcpu, int reg, - struct seg_desc *desc) +vm_set_seg_desc(struct vcpu *vcpu, int reg, struct seg_desc *desc) { - if (vcpu < 0 || vcpu >= vm->maxcpus) - return (EINVAL); if (!is_segment_register(reg) && !is_descriptor_table(reg)) return (EINVAL); - return (vmmops_setdesc(vcpu_cookie(vm, vcpu), reg, desc)); + return (vmmops_setdesc(vcpu->cookie, reg, desc)); } static void @@ -1228,13 +1219,11 @@ static VMM_STAT(VCPU_IDLE_TICKS, "number of ticks vcpu was idle"); static int -vcpu_set_state_locked(struct vm *vm, int vcpuid, enum vcpu_state newstate, +vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate, bool from_idle) { - struct vcpu *vcpu; int error; - vcpu = &vm->vcpu[vcpuid]; vcpu_assert_locked(vcpu); /* @@ -1246,7 +1235,7 @@ while (vcpu->state != VCPU_IDLE) { vcpu->reqidle = 1; vcpu_notify_event_locked(vcpu, false); - VCPU_CTR1(vm, vcpuid, "vcpu state change from %s to " + VMM_CTR1(vcpu, "vcpu state change from %s to " "idle requested", vcpu_state2str(vcpu->state)); msleep_spin(&vcpu->state, &vcpu->mtx, "vmstat", hz); } @@ -1286,7 +1275,7 @@ if (error) return (EBUSY); - VCPU_CTR2(vm, vcpuid, "vcpu state changed from %s to %s", + VMM_CTR2(vcpu, "vcpu state changed from %s to %s", vcpu_state2str(vcpu->state), vcpu_state2str(newstate)); vcpu->state = newstate; @@ -1302,20 +1291,20 @@ } static void -vcpu_require_state(struct vm *vm, int vcpuid, enum vcpu_state newstate) +vcpu_require_state(struct vcpu *vcpu, enum vcpu_state newstate) { int error; - if ((error = vcpu_set_state(vm, vcpuid, newstate, false)) != 0) + if ((error = vcpu_set_state(vcpu, newstate, false)) != 0) panic("Error %d setting state to %d\n", error, newstate); } static void -vcpu_require_state_locked(struct vm *vm, int vcpuid, enum vcpu_state newstate) +vcpu_require_state_locked(struct vcpu *vcpu, enum vcpu_state newstate) { int error; - if ((error = vcpu_set_state_locked(vm, vcpuid, newstate, false)) != 0) + if ((error = vcpu_set_state_locked(vcpu, newstate, false)) != 0) panic("Error %d setting state to %d", error, newstate); } @@ -1366,21 +1355,21 @@ * Emulate a guest 'hlt' by sleeping until the vcpu is ready to run. */ static int -vm_handle_hlt(struct vm *vm, int vcpuid, bool intr_disabled, bool *retu) +vm_handle_hlt(struct vcpu *vcpu, bool intr_disabled, bool *retu) { - struct vcpu *vcpu; + struct vm *vm = vcpu->vm; const char *wmesg; struct thread *td; - int error, t, vcpu_halted, vm_halted; + int error, t, vcpuid, vcpu_halted, vm_halted; - KASSERT(!CPU_ISSET(vcpuid, &vm->halted_cpus), ("vcpu already halted")); - - vcpu = &vm->vcpu[vcpuid]; + vcpuid = vcpu->vcpuid; vcpu_halted = 0; vm_halted = 0; error = 0; td = curthread; + KASSERT(!CPU_ISSET(vcpuid, &vm->halted_cpus), ("vcpu already halted")); + vcpu_lock(vcpu); while (1) { /* @@ -1418,7 +1407,7 @@ */ if (intr_disabled) { wmesg = "vmhalt"; - VCPU_CTR0(vm, vcpuid, "Halted"); + VMM_CTR0(vcpu, "Halted"); if (!vcpu_halted && halt_detection_enabled) { vcpu_halted = 1; CPU_SET_ATOMIC(vcpuid, &vm->halted_cpus); @@ -1432,13 +1421,13 @@ } t = ticks; - vcpu_require_state_locked(vm, vcpuid, VCPU_SLEEPING); + vcpu_require_state_locked(vcpu, VCPU_SLEEPING); /* * XXX msleep_spin() cannot be interrupted by signals so * wake up periodically to check pending signals. */ msleep_spin(vcpu, &vcpu->mtx, wmesg, hz); - vcpu_require_state_locked(vm, vcpuid, VCPU_FROZEN); + vcpu_require_state_locked(vcpu, VCPU_FROZEN); vmm_stat_incr(vcpu, VCPU_IDLE_TICKS, ticks - t); if (td_ast_pending(td, TDA_SUSPEND)) { vcpu_unlock(vcpu); @@ -1466,14 +1455,13 @@ } static int -vm_handle_paging(struct vm *vm, int vcpuid, bool *retu) +vm_handle_paging(struct vcpu *vcpu, bool *retu) { + struct vm *vm = vcpu->vm; int rv, ftype; struct vm_map *map; - struct vcpu *vcpu; struct vm_exit *vme; - vcpu = &vm->vcpu[vcpuid]; vme = &vcpu->exitinfo; KASSERT(vme->inst_length == 0, ("%s: invalid inst_length %d", @@ -1488,7 +1476,7 @@ rv = pmap_emulate_accessed_dirty(vmspace_pmap(vm->vmspace), vme->u.paging.gpa, ftype); if (rv == 0) { - VCPU_CTR2(vm, vcpuid, "%s bit emulation for gpa %#lx", + VMM_CTR2(vcpu, "%s bit emulation for gpa %#lx", ftype == VM_PROT_READ ? "accessed" : "dirty", vme->u.paging.gpa); goto done; @@ -1498,7 +1486,7 @@ map = &vm->vmspace->vm_map; rv = vm_fault(map, vme->u.paging.gpa, ftype, VM_FAULT_NORMAL, NULL); - VCPU_CTR3(vm, vcpuid, "vm_handle_paging rv = %d, gpa = %#lx, " + VMM_CTR3(vcpu, "vm_handle_paging rv = %d, gpa = %#lx, " "ftype = %d", rv, vme->u.paging.gpa, ftype); if (rv != KERN_SUCCESS) @@ -1508,10 +1496,9 @@ } static int -vm_handle_inst_emul(struct vm *vm, int vcpuid, bool *retu) +vm_handle_inst_emul(struct vcpu *vcpu, bool *retu) { struct vie *vie; - struct vcpu *vcpu; struct vm_exit *vme; uint64_t gla, gpa, cs_base; struct vm_guest_paging *paging; @@ -1520,7 +1507,6 @@ enum vm_cpu_mode cpu_mode; int cs_d, error, fault; - vcpu = &vm->vcpu[vcpuid]; vme = &vcpu->exitinfo; KASSERT(vme->inst_length == 0, ("%s: invalid inst_length %d", @@ -1534,7 +1520,7 @@ paging = &vme->u.inst_emul.paging; cpu_mode = paging->cpu_mode; - VCPU_CTR1(vm, vcpuid, "inst_emul fault accessing gpa %#lx", gpa); + VMM_CTR1(vcpu, "inst_emul fault accessing gpa %#lx", gpa); /* Fetch, decode and emulate the faulting instruction */ if (vie->num_valid == 0) { @@ -1550,7 +1536,7 @@ return (error); if (vmm_decode_instruction(vcpu, gla, cpu_mode, cs_d, vie) != 0) { - VCPU_CTR1(vm, vcpuid, "Error decoding instruction at %#lx", + VMM_CTR1(vcpu, "Error decoding instruction at %#lx", vme->rip + cs_base); *retu = true; /* dump instruction bytes in userspace */ return (0); @@ -1561,8 +1547,8 @@ */ vme->inst_length = vie->num_processed; vcpu->nextrip += vie->num_processed; - VCPU_CTR1(vm, vcpuid, "nextrip updated to %#lx after instruction " - "decoding", vcpu->nextrip); + VMM_CTR1(vcpu, "nextrip updated to %#lx after instruction decoding", + vcpu->nextrip); /* return to userland unless this is an in-kernel emulated device */ if (gpa >= DEFAULT_APIC_BASE && gpa < DEFAULT_APIC_BASE + PAGE_SIZE) { @@ -1586,17 +1572,16 @@ } static int -vm_handle_suspend(struct vm *vm, int vcpuid, bool *retu) +vm_handle_suspend(struct vcpu *vcpu, bool *retu) { + struct vm *vm = vcpu->vm; int error, i; - struct vcpu *vcpu; struct thread *td; error = 0; - vcpu = &vm->vcpu[vcpuid]; td = curthread; - CPU_SET_ATOMIC(vcpuid, &vm->suspended_cpus); + CPU_SET_ATOMIC(vcpu->vcpuid, &vm->suspended_cpus); /* * Wait until all 'active_cpus' have suspended themselves. @@ -1608,22 +1593,22 @@ vcpu_lock(vcpu); while (error == 0) { if (CPU_CMP(&vm->suspended_cpus, &vm->active_cpus) == 0) { - VCPU_CTR0(vm, vcpuid, "All vcpus suspended"); + VMM_CTR0(vcpu, "All vcpus suspended"); break; } if (vm->rendezvous_func == NULL) { - VCPU_CTR0(vm, vcpuid, "Sleeping during suspend"); - vcpu_require_state_locked(vm, vcpuid, VCPU_SLEEPING); + VMM_CTR0(vcpu, "Sleeping during suspend"); + vcpu_require_state_locked(vcpu, VCPU_SLEEPING); msleep_spin(vcpu, &vcpu->mtx, "vmsusp", hz); - vcpu_require_state_locked(vm, vcpuid, VCPU_FROZEN); + vcpu_require_state_locked(vcpu, VCPU_FROZEN); if (td_ast_pending(td, TDA_SUSPEND)) { vcpu_unlock(vcpu); error = thread_check_susp(td, false); vcpu_lock(vcpu); } } else { - VCPU_CTR0(vm, vcpuid, "Rendezvous during suspend"); + VMM_CTR0(vcpu, "Rendezvous during suspend"); vcpu_unlock(vcpu); error = vm_handle_rendezvous(vcpu); vcpu_lock(vcpu); @@ -1636,7 +1621,7 @@ */ for (i = 0; i < vm->maxcpus; i++) { if (CPU_ISSET(i, &vm->suspended_cpus)) { - vcpu_notify_event(vm, i, false); + vcpu_notify_event(vm_vcpu(vm, i), false); } } @@ -1645,10 +1630,8 @@ } static int -vm_handle_reqidle(struct vm *vm, int vcpuid, bool *retu) +vm_handle_reqidle(struct vcpu *vcpu, bool *retu) { - struct vcpu *vcpu = &vm->vcpu[vcpuid]; - vcpu_lock(vcpu); KASSERT(vcpu->reqidle, ("invalid vcpu reqidle %d", vcpu->reqidle)); vcpu->reqidle = 0; @@ -1678,7 +1661,7 @@ */ for (i = 0; i < vm->maxcpus; i++) { if (CPU_ISSET(i, &vm->active_cpus)) - vcpu_notify_event(vm, i, false); + vcpu_notify_event(vm_vcpu(vm, i), false); } return (0); @@ -1751,21 +1734,18 @@ } int -vm_run(struct vm *vm, struct vm_run *vmrun) +vm_run(struct vcpu *vcpu, struct vm_exit *vme_user) { + struct vm *vm = vcpu->vm; struct vm_eventinfo evinfo; int error, vcpuid; - struct vcpu *vcpu; struct pcb *pcb; uint64_t tscval; struct vm_exit *vme; bool retu, intr_disabled; pmap_t pmap; - vcpuid = vmrun->cpuid; - - if (vcpuid < 0 || vcpuid >= vm->maxcpus) - return (EINVAL); + vcpuid = vcpu->vcpuid; if (!CPU_ISSET(vcpuid, &vm->active_cpus)) return (EINVAL); @@ -1774,7 +1754,6 @@ return (EINVAL); pmap = vmspace_pmap(vm->vmspace); - vcpu = &vm->vcpu[vcpuid]; vme = &vcpu->exitinfo; evinfo.rptr = &vm->rendezvous_func; evinfo.sptr = &vm->suspend; @@ -1792,9 +1771,9 @@ restore_guest_fpustate(vcpu); - vcpu_require_state(vm, vcpuid, VCPU_RUNNING); + vcpu_require_state(vcpu, VCPU_RUNNING); error = vmmops_run(vcpu->cookie, vcpu->nextrip, pmap, &evinfo); - vcpu_require_state(vm, vcpuid, VCPU_FROZEN); + vcpu_require_state(vcpu, VCPU_FROZEN); save_guest_fpustate(vcpu); @@ -1807,10 +1786,10 @@ vcpu->nextrip = vme->rip + vme->inst_length; switch (vme->exitcode) { case VM_EXITCODE_REQIDLE: - error = vm_handle_reqidle(vm, vcpuid, &retu); + error = vm_handle_reqidle(vcpu, &retu); break; case VM_EXITCODE_SUSPENDED: - error = vm_handle_suspend(vm, vcpuid, &retu); + error = vm_handle_suspend(vcpu, &retu); break; case VM_EXITCODE_IOAPIC_EOI: vioapic_process_eoi(vm, vme->u.ioapic_eoi.vector); @@ -1820,17 +1799,17 @@ break; case VM_EXITCODE_HLT: intr_disabled = ((vme->u.hlt.rflags & PSL_I) == 0); - error = vm_handle_hlt(vm, vcpuid, intr_disabled, &retu); + error = vm_handle_hlt(vcpu, intr_disabled, &retu); break; case VM_EXITCODE_PAGING: - error = vm_handle_paging(vm, vcpuid, &retu); + error = vm_handle_paging(vcpu, &retu); break; case VM_EXITCODE_INST_EMUL: - error = vm_handle_inst_emul(vm, vcpuid, &retu); + error = vm_handle_inst_emul(vcpu, &retu); break; case VM_EXITCODE_INOUT: case VM_EXITCODE_INOUT_STR: - error = vm_handle_inout(vm, vcpuid, vme, &retu); + error = vm_handle_inout(vcpu, vme, &retu); break; case VM_EXITCODE_MONITOR: case VM_EXITCODE_MWAIT: @@ -1856,10 +1835,10 @@ goto restart; vmm_stat_incr(vcpu, VMEXIT_USERSPACE, 1); - VCPU_CTR2(vm, vcpuid, "retu %d/%d", error, vme->exitcode); + VMM_CTR2(vcpu, "retu %d/%d", error, vme->exitcode); /* copy the exit information */ - bcopy(vme, &vmrun->vm_exit, sizeof(struct vm_exit)); + *vme_user = *vme; return (error); } @@ -2071,14 +2050,8 @@ } int -vm_get_intinfo(struct vm *vm, int vcpuid, uint64_t *info1, uint64_t *info2) +vm_get_intinfo(struct vcpu *vcpu, uint64_t *info1, uint64_t *info2) { - struct vcpu *vcpu; - - if (vcpuid < 0 || vcpuid >= vm->maxcpus) - return (EINVAL); - - vcpu = &vm->vcpu[vcpuid]; *info1 = vcpu->exitintinfo; *info2 = vcpu_exception_intinfo(vcpu); return (0); @@ -2168,17 +2141,11 @@ static VMM_STAT(VCPU_NMI_COUNT, "number of NMIs delivered to vcpu"); int -vm_inject_nmi(struct vm *vm, int vcpuid) +vm_inject_nmi(struct vcpu *vcpu) { - struct vcpu *vcpu; - - if (vcpuid < 0 || vcpuid >= vm->maxcpus) - return (EINVAL); - - vcpu = &vm->vcpu[vcpuid]; vcpu->nmi_pending = 1; - vcpu_notify_event(vm, vcpuid, false); + vcpu_notify_event(vcpu, false); return (0); } @@ -2201,17 +2168,11 @@ static VMM_STAT(VCPU_EXTINT_COUNT, "number of ExtINTs delivered to vcpu"); int -vm_inject_extint(struct vm *vm, int vcpuid) +vm_inject_extint(struct vcpu *vcpu) { - struct vcpu *vcpu; - - if (vcpuid < 0 || vcpuid >= vm->maxcpus) - return (EINVAL); - - vcpu = &vm->vcpu[vcpuid]; vcpu->extint_pending = 1; - vcpu_notify_event(vm, vcpuid, false); + vcpu_notify_event(vcpu, false); return (0); } @@ -2232,27 +2193,21 @@ } int -vm_get_capability(struct vm *vm, int vcpu, int type, int *retval) +vm_get_capability(struct vcpu *vcpu, int type, int *retval) { - if (vcpu < 0 || vcpu >= vm->maxcpus) - return (EINVAL); - if (type < 0 || type >= VM_CAP_MAX) return (EINVAL); - return (vmmops_getcap(vcpu_cookie(vm, vcpu), type, retval)); + return (vmmops_getcap(vcpu->cookie, type, retval)); } int -vm_set_capability(struct vm *vm, int vcpu, int type, int val) +vm_set_capability(struct vcpu *vcpu, int type, int val) { - if (vcpu < 0 || vcpu >= vm->maxcpus) - return (EINVAL); - if (type < 0 || type >= VM_CAP_MAX) return (EINVAL); - return (vmmops_setcap(vcpu_cookie(vm, vcpu), type, val)); + return (vmmops_setcap(vcpu->cookie, type, val)); } struct vm * @@ -2343,19 +2298,12 @@ } int -vcpu_set_state(struct vm *vm, int vcpuid, enum vcpu_state newstate, - bool from_idle) +vcpu_set_state(struct vcpu *vcpu, enum vcpu_state newstate, bool from_idle) { int error; - struct vcpu *vcpu; - - if (vcpuid < 0 || vcpuid >= vm->maxcpus) - panic("vm_set_run_state: invalid vcpuid %d", vcpuid); - - vcpu = &vm->vcpu[vcpuid]; vcpu_lock(vcpu); - error = vcpu_set_state_locked(vm, vcpuid, newstate, from_idle); + error = vcpu_set_state_locked(vcpu, newstate, from_idle); vcpu_unlock(vcpu); return (error); @@ -2376,58 +2324,48 @@ } int -vm_activate_cpu(struct vm *vm, int vcpuid) +vm_activate_cpu(struct vcpu *vcpu) { + struct vm *vm = vcpu->vm; - if (vcpuid < 0 || vcpuid >= vm->maxcpus) - return (EINVAL); - - if (CPU_ISSET(vcpuid, &vm->active_cpus)) + if (CPU_ISSET(vcpu->vcpuid, &vm->active_cpus)) return (EBUSY); - VCPU_CTR0(vm, vcpuid, "activated"); - CPU_SET_ATOMIC(vcpuid, &vm->active_cpus); + VMM_CTR0(vcpu, "activated"); + CPU_SET_ATOMIC(vcpu->vcpuid, &vm->active_cpus); return (0); } int -vm_suspend_cpu(struct vm *vm, int vcpuid) +vm_suspend_cpu(struct vm *vm, struct vcpu *vcpu) { - int i; - - if (vcpuid < -1 || vcpuid >= vm->maxcpus) - return (EINVAL); - - if (vcpuid == -1) { + if (vcpu == NULL) { vm->debug_cpus = vm->active_cpus; - for (i = 0; i < vm->maxcpus; i++) { + for (int i = 0; i < vm->maxcpus; i++) { if (CPU_ISSET(i, &vm->active_cpus)) - vcpu_notify_event(vm, i, false); + vcpu_notify_event(vm_vcpu(vm, i), false); } } else { - if (!CPU_ISSET(vcpuid, &vm->active_cpus)) + if (!CPU_ISSET(vcpu->vcpuid, &vm->active_cpus)) return (EINVAL); - CPU_SET_ATOMIC(vcpuid, &vm->debug_cpus); - vcpu_notify_event(vm, vcpuid, false); + CPU_SET_ATOMIC(vcpu->vcpuid, &vm->debug_cpus); + vcpu_notify_event(vcpu, false); } return (0); } int -vm_resume_cpu(struct vm *vm, int vcpuid) +vm_resume_cpu(struct vm *vm, struct vcpu *vcpu) { - if (vcpuid < -1 || vcpuid >= vm->maxcpus) - return (EINVAL); - - if (vcpuid == -1) { + if (vcpu == NULL) { CPU_ZERO(&vm->debug_cpus); } else { - if (!CPU_ISSET(vcpuid, &vm->debug_cpus)) + if (!CPU_ISSET(vcpu->vcpuid, &vm->debug_cpus)) return (EINVAL); - CPU_CLR_ATOMIC(vcpuid, &vm->debug_cpus); + CPU_CLR_ATOMIC(vcpu->vcpuid, &vm->debug_cpus); } return (0); } @@ -2468,28 +2406,19 @@ } int -vm_get_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state *state) +vm_get_x2apic_state(struct vcpu *vcpu, enum x2apic_state *state) { - if (vcpuid < 0 || vcpuid >= vm->maxcpus) - return (EINVAL); - - *state = vm->vcpu[vcpuid].x2apic_state; + *state = vcpu->x2apic_state; return (0); } int -vm_set_x2apic_state(struct vm *vm, int vcpuid, enum x2apic_state state) +vm_set_x2apic_state(struct vcpu *vcpu, enum x2apic_state state) { - struct vcpu *vcpu; - - if (vcpuid < 0 || vcpuid >= vm->maxcpus) - return (EINVAL); - if (state >= X2APIC_STATE_LAST) return (EINVAL); - vcpu = &vm->vcpu[vcpuid]; vcpu->x2apic_state = state; vlapic_set_x2apic_state(vcpu, state); @@ -2536,10 +2465,8 @@ } void -vcpu_notify_event(struct vm *vm, int vcpuid, bool lapic_intr) +vcpu_notify_event(struct vcpu *vcpu, bool lapic_intr) { - struct vcpu *vcpu = &vm->vcpu[vcpuid]; - vcpu_lock(vcpu); vcpu_notify_event_locked(vcpu, lapic_intr); vcpu_unlock(vcpu); @@ -2578,7 +2505,7 @@ if (vm->rendezvous_func != NULL) { /* * If a rendezvous is already in progress then we need to - * call the rendezvous handler in case this 'vcpuid' is one + * call the rendezvous handler in case this 'vcpu' is one * of the targets of the rendezvous. */ VMM_CTR0(vcpu, "Rendezvous already in progress"); @@ -2604,7 +2531,7 @@ */ for (i = 0; i < vm->maxcpus; i++) { if (CPU_ISSET(i, &dest)) - vcpu_notify_event(vm, i, false); + vcpu_notify_event(vm_vcpu(vm, i), false); } return (vm_handle_rendezvous(vcpu)); @@ -2751,22 +2678,22 @@ VMM_STAT_DECLARE(VMM_MEM_WIRED); static void -vm_get_rescnt(struct vm *vm, int vcpu, struct vmm_stat_type *stat) +vm_get_rescnt(struct vcpu *vcpu, struct vmm_stat_type *stat) { - if (vcpu == 0) { - vmm_stat_set(vm_vcpu(vm, vcpu), VMM_MEM_RESIDENT, - PAGE_SIZE * vmspace_resident_count(vm->vmspace)); + if (vcpu->vcpuid == 0) { + vmm_stat_set(vcpu, VMM_MEM_RESIDENT, PAGE_SIZE * + vmspace_resident_count(vcpu->vm->vmspace)); } } static void -vm_get_wiredcnt(struct vm *vm, int vcpu, struct vmm_stat_type *stat) +vm_get_wiredcnt(struct vcpu *vcpu, struct vmm_stat_type *stat) { - if (vcpu == 0) { - vmm_stat_set(vm_vcpu(vm, vcpu), VMM_MEM_WIRED, - PAGE_SIZE * pmap_wired_count(vmspace_pmap(vm->vmspace))); + if (vcpu->vcpuid == 0) { + vmm_stat_set(vcpu, VMM_MEM_WIRED, PAGE_SIZE * + pmap_wired_count(vmspace_pmap(vcpu->vm->vmspace))); } } diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c --- a/sys/amd64/vmm/vmm_dev.c +++ b/sys/amd64/vmm/vmm_dev.c @@ -131,22 +131,24 @@ if (vcpu < 0 || vcpu >= vm_get_maxcpus(sc->vm)) return (EINVAL); - error = vcpu_set_state(sc->vm, vcpu, VCPU_FROZEN, true); + error = vcpu_set_state(vm_vcpu(sc->vm, vcpu), VCPU_FROZEN, true); return (error); } static void -vcpu_unlock_one(struct vmmdev_softc *sc, int vcpu) +vcpu_unlock_one(struct vmmdev_softc *sc, int vcpuid) { + struct vcpu *vcpu; enum vcpu_state state; - state = vcpu_get_state(vm_vcpu(sc->vm, vcpu), NULL); + vcpu = vm_vcpu(sc->vm, vcpuid); + state = vcpu_get_state(vcpu, NULL); if (state != VCPU_FROZEN) { panic("vcpu %s(%d) has invalid state %d", vm_name(sc->vm), - vcpu, state); + vcpuid, state); } - vcpu_set_state(sc->vm, vcpu, VCPU_IDLE, false); + vcpu_set_state(vcpu, VCPU_IDLE, false); } static int @@ -366,6 +368,15 @@ return (error); } +static struct vcpu * +lookup_vcpu(struct vm *vm, int vcpuid) +{ + if (vcpuid < 0 || vcpuid >= vm_get_maxcpus(vm)) + return (NULL); + + return (vm_vcpu(vm, vcpuid)); +} + static int vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, struct thread *td) @@ -389,7 +400,6 @@ struct vm_pptdev_mmio *pptmmio; struct vm_pptdev_msi *pptmsi; struct vm_pptdev_msix *pptmsix; - struct vm_nmi *vmnmi; #ifdef COMPAT_FREEBSD13 struct vm_stats_old *vmstats_old; #endif @@ -399,7 +409,6 @@ struct vm_gpa_pte *gpapte; struct vm_suspend *vmsuspend; struct vm_gla2gpa *gg; - struct vm_activate_cpu *vac; struct vm_cpuset *vm_cpuset; struct vm_intinfo *vmii; struct vm_rtc_time *rtctime; @@ -427,7 +436,13 @@ state_changed = 0; /* - * Some VMM ioctls can operate only on vcpus that are not running. + * For VMM ioctls that operate on a single vCPU, lookup the + * vcpu. For VMM ioctls which require one or more vCPUs to + * not be running, lock necessary vCPUs. + * + * XXX fragile, handle with care + * Most of these assume that the first field of the ioctl data + * is the vcpuid. */ switch (cmd) { case VM_RUN: @@ -450,8 +465,7 @@ case VM_GET_INTINFO: case VM_RESTART_INSTRUCTION: /* - * XXX fragile, handle with care - * Assumes that the first field of the ioctl data is the vcpu. + * ioctls that can operate only on vcpus that are not running. */ vcpuid = *(int *)data; error = vcpu_lock_one(sc, vcpuid); @@ -498,6 +512,42 @@ state_changed = 1; break; +#ifdef COMPAT_FREEBSD13 + case VM_STATS_OLD: +#endif + case VM_STATS: + case VM_INJECT_NMI: + case VM_LAPIC_IRQ: + case VM_GET_X2APIC_STATE: + /* + * These do not need the vCPU locked but do operate on + * a specific vCPU. + */ + vcpuid = *(int *)data; + vcpu = lookup_vcpu(sc->vm, vcpuid); + if (vcpu == NULL) { + error = EINVAL; + goto done; + } + break; + + case VM_LAPIC_LOCAL_IRQ: + case VM_SUSPEND_CPU: + case VM_RESUME_CPU: + /* + * These can either operate on all CPUs via a vcpuid of + * -1 or on a specific vCPU. + */ + vcpuid = *(int *)data; + if (vcpuid == -1) + break; + vcpu = lookup_vcpu(sc->vm, vcpuid); + if (vcpu == NULL) { + error = EINVAL; + goto done; + } + break; + default: break; } @@ -505,7 +555,7 @@ switch(cmd) { case VM_RUN: vmrun = (struct vm_run *)data; - error = vm_run(sc->vm, vmrun); + error = vm_run(vcpu, &vmrun->vm_exit); break; case VM_SUSPEND: vmsuspend = (struct vm_suspend *)data; @@ -524,7 +574,7 @@ case VM_STATS_OLD: vmstats_old = (struct vm_stats_old *)data; getmicrotime(&vmstats_old->tv); - error = vmm_stat_copy(sc->vm, vmstats_old->cpuid, 0, + error = vmm_stat_copy(vcpu, 0, nitems(vmstats_old->statbuf), &vmstats_old->num_entries, vmstats_old->statbuf); @@ -533,7 +583,7 @@ case VM_STATS: { vmstats = (struct vm_stats *)data; getmicrotime(&vmstats->tv); - error = vmm_stat_copy(sc->vm, vmstats->cpuid, vmstats->index, + error = vmm_stat_copy(vcpu, vmstats->index, nitems(vmstats->statbuf), &vmstats->num_entries, vmstats->statbuf); break; @@ -586,17 +636,15 @@ vmexc->restart_instruction); break; case VM_INJECT_NMI: - vmnmi = (struct vm_nmi *)data; - error = vm_inject_nmi(sc->vm, vmnmi->cpuid); + error = vm_inject_nmi(vcpu); break; case VM_LAPIC_IRQ: vmirq = (struct vm_lapic_irq *)data; - error = lapic_intr_edge(sc->vm, vmirq->cpuid, vmirq->vector); + error = lapic_intr_edge(vcpu, vmirq->vector); break; case VM_LAPIC_LOCAL_IRQ: vmirq = (struct vm_lapic_irq *)data; - error = lapic_set_local_intr(sc->vm, vmirq->cpuid, - vmirq->vector); + error = lapic_set_local_intr(sc->vm, vcpu, vmirq->vector); break; case VM_LAPIC_MSI: vmmsi = (struct vm_lapic_msi *)data; @@ -721,7 +769,7 @@ break; case VM_SET_SEGMENT_DESCRIPTOR: vmsegdesc = (struct vm_seg_desc *)data; - error = vm_set_seg_desc(sc->vm, vmsegdesc->cpuid, + error = vm_set_seg_desc(vcpu, vmsegdesc->regnum, &vmsegdesc->desc); break; @@ -775,25 +823,23 @@ break; case VM_GET_CAPABILITY: vmcap = (struct vm_capability *)data; - error = vm_get_capability(sc->vm, vmcap->cpuid, + error = vm_get_capability(vcpu, vmcap->captype, &vmcap->capval); break; case VM_SET_CAPABILITY: vmcap = (struct vm_capability *)data; - error = vm_set_capability(sc->vm, vmcap->cpuid, + error = vm_set_capability(vcpu, vmcap->captype, vmcap->capval); break; case VM_SET_X2APIC_STATE: x2apic = (struct vm_x2apic *)data; - error = vm_set_x2apic_state(sc->vm, - x2apic->cpuid, x2apic->state); + error = vm_set_x2apic_state(vcpu, x2apic->state); break; case VM_GET_X2APIC_STATE: x2apic = (struct vm_x2apic *)data; - error = vm_get_x2apic_state(sc->vm, - x2apic->cpuid, &x2apic->state); + error = vm_get_x2apic_state(vcpu, &x2apic->state); break; case VM_GET_GPA_PMAP: gpapte = (struct vm_gpa_pte *)data; @@ -823,8 +869,7 @@ ("%s: vm_gla2gpa unknown error %d", __func__, error)); break; case VM_ACTIVATE_CPU: - vac = (struct vm_activate_cpu *)data; - error = vm_activate_cpu(sc->vm, vac->vcpuid); + error = vm_activate_cpu(vcpu); break; case VM_GET_CPUS: error = 0; @@ -848,12 +893,10 @@ free(cpuset, M_TEMP); break; case VM_SUSPEND_CPU: - vac = (struct vm_activate_cpu *)data; - error = vm_suspend_cpu(sc->vm, vac->vcpuid); + error = vm_suspend_cpu(sc->vm, vcpu); break; case VM_RESUME_CPU: - vac = (struct vm_activate_cpu *)data; - error = vm_resume_cpu(sc->vm, vac->vcpuid); + error = vm_resume_cpu(sc->vm, vcpu); break; case VM_SET_INTINFO: vmii = (struct vm_intinfo *)data; @@ -861,8 +904,7 @@ break; case VM_GET_INTINFO: vmii = (struct vm_intinfo *)data; - error = vm_get_intinfo(sc->vm, vmii->vcpuid, &vmii->info1, - &vmii->info2); + error = vm_get_intinfo(vcpu, &vmii->info1, &vmii->info2); break; case VM_RTC_WRITE: rtcdata = (struct vm_rtc_data *)data; diff --git a/sys/amd64/vmm/vmm_ioport.h b/sys/amd64/vmm/vmm_ioport.h --- a/sys/amd64/vmm/vmm_ioport.h +++ b/sys/amd64/vmm/vmm_ioport.h @@ -34,6 +34,6 @@ typedef int (*ioport_handler_func_t)(struct vm *vm, bool in, int port, int bytes, uint32_t *val); -int vm_handle_inout(struct vm *vm, int vcpuid, struct vm_exit *vme, bool *retu); +int vm_handle_inout(struct vcpu *vcpu, struct vm_exit *vme, bool *retu); #endif /* _VMM_IOPORT_H_ */ diff --git a/sys/amd64/vmm/vmm_ioport.c b/sys/amd64/vmm/vmm_ioport.c --- a/sys/amd64/vmm/vmm_ioport.c +++ b/sys/amd64/vmm/vmm_ioport.c @@ -100,8 +100,7 @@ #endif /* KTR */ static int -emulate_inout_port(struct vm *vm, int vcpuid, struct vm_exit *vmexit, - bool *retu) +emulate_inout_port(struct vcpu *vcpu, struct vm_exit *vmexit, bool *retu) { ioport_handler_func_t handler; uint32_t mask, val; @@ -122,8 +121,8 @@ val = vmexit->u.inout.eax & mask; } - error = (*handler)(vm, vmexit->u.inout.in, vmexit->u.inout.port, - vmexit->u.inout.bytes, &val); + error = (*handler)(vcpu_vm(vcpu), vmexit->u.inout.in, + vmexit->u.inout.port, vmexit->u.inout.bytes, &val); if (error) { /* * The value returned by this function is also the return value @@ -138,7 +137,7 @@ if (vmexit->u.inout.in) { vmexit->u.inout.eax &= ~mask; vmexit->u.inout.eax |= val & mask; - error = vm_set_register(vm_vcpu(vm, vcpuid), VM_REG_GUEST_RAX, + error = vm_set_register(vcpu, VM_REG_GUEST_RAX, vmexit->u.inout.eax); KASSERT(error == 0, ("emulate_ioport: error %d setting guest " "rax register", error)); @@ -148,14 +147,14 @@ } static int -emulate_inout_str(struct vm *vm, int vcpuid, struct vm_exit *vmexit, bool *retu) +emulate_inout_str(struct vcpu *vcpu, struct vm_exit *vmexit, bool *retu) { *retu = true; return (0); /* Return to userspace to finish emulation */ } int -vm_handle_inout(struct vm *vm, int vcpuid, struct vm_exit *vmexit, bool *retu) +vm_handle_inout(struct vcpu *vcpu, struct vm_exit *vmexit, bool *retu) { int bytes __diagused, error; @@ -164,11 +163,11 @@ ("vm_handle_inout: invalid operand size %d", bytes)); if (vmexit->u.inout.string) - error = emulate_inout_str(vm, vcpuid, vmexit, retu); + error = emulate_inout_str(vcpu, vmexit, retu); else - error = emulate_inout_port(vm, vcpuid, vmexit, retu); + error = emulate_inout_port(vcpu, vmexit, retu); - VCPU_CTR4(vm, vcpuid, "%s%s 0x%04x: %s", + VCPU_CTR4(vcpu_vm(vcpu), vcpu_vcpuid(vcpu), "%s%s 0x%04x: %s", vmexit->u.inout.rep ? "rep " : "", inout_instruction(vmexit), vmexit->u.inout.port, diff --git a/sys/amd64/vmm/vmm_lapic.h b/sys/amd64/vmm/vmm_lapic.h --- a/sys/amd64/vmm/vmm_lapic.h +++ b/sys/amd64/vmm/vmm_lapic.h @@ -47,29 +47,29 @@ * Signals to the LAPIC that an interrupt at 'vector' needs to be generated * to the 'cpu', the state is recorded in IRR. */ -int lapic_set_intr(struct vm *vm, int cpu, int vector, bool trig); +int lapic_set_intr(struct vcpu *vcpu, int vector, bool trig); #define LAPIC_TRIG_LEVEL true #define LAPIC_TRIG_EDGE false static __inline int -lapic_intr_level(struct vm *vm, int cpu, int vector) +lapic_intr_level(struct vcpu *vcpu, int vector) { - return (lapic_set_intr(vm, cpu, vector, LAPIC_TRIG_LEVEL)); + return (lapic_set_intr(vcpu, vector, LAPIC_TRIG_LEVEL)); } static __inline int -lapic_intr_edge(struct vm *vm, int cpu, int vector) +lapic_intr_edge(struct vcpu *vcpu, int vector) { - return (lapic_set_intr(vm, cpu, vector, LAPIC_TRIG_EDGE)); + return (lapic_set_intr(vcpu, vector, LAPIC_TRIG_EDGE)); } /* * Triggers the LAPIC local interrupt (LVT) 'vector' on 'cpu'. 'cpu' can * be set to -1 to trigger the interrupt on all CPUs. */ -int lapic_set_local_intr(struct vm *vm, int cpu, int vector); +int lapic_set_local_intr(struct vm *vm, struct vcpu *vcpu, int vector); int lapic_intr_msi(struct vm *vm, uint64_t addr, uint64_t msg); diff --git a/sys/amd64/vmm/vmm_lapic.c b/sys/amd64/vmm/vmm_lapic.c --- a/sys/amd64/vmm/vmm_lapic.c +++ b/sys/amd64/vmm/vmm_lapic.c @@ -52,13 +52,10 @@ #define MSI_X86_ADDR_LOG 0x00000004 /* Destination Mode */ int -lapic_set_intr(struct vm *vm, int cpu, int vector, bool level) +lapic_set_intr(struct vcpu *vcpu, int vector, bool level) { struct vlapic *vlapic; - if (cpu < 0 || cpu >= vm_get_maxcpus(vm)) - return (EINVAL); - /* * According to section "Maskable Hardware Interrupts" in Intel SDM * vectors 16 through 255 can be delivered through the local APIC. @@ -66,32 +63,31 @@ if (vector < 16 || vector > 255) return (EINVAL); - vlapic = vm_lapic(vm_vcpu(vm, cpu)); + vlapic = vm_lapic(vcpu); if (vlapic_set_intr_ready(vlapic, vector, level)) - vcpu_notify_event(vm, cpu, true); + vcpu_notify_event(vcpu, true); return (0); } int -lapic_set_local_intr(struct vm *vm, int cpu, int vector) +lapic_set_local_intr(struct vm *vm, struct vcpu *vcpu, int vector) { struct vlapic *vlapic; cpuset_t dmask; - int error; + int cpu, error; - if (cpu < -1 || cpu >= vm_get_maxcpus(vm)) - return (EINVAL); - - if (cpu == -1) + if (vcpu == NULL) { + error = 0; dmask = vm_active_cpus(vm); - else - CPU_SETOF(cpu, &dmask); - error = 0; - CPU_FOREACH_ISSET(cpu, &dmask) { - vlapic = vm_lapic(vm_vcpu(vm, cpu)); + CPU_FOREACH_ISSET(cpu, &dmask) { + vlapic = vm_lapic(vm_vcpu(vm, cpu)); + error = vlapic_trigger_lvt(vlapic, vector); + if (error) + break; + } + } else { + vlapic = vm_lapic(vcpu); error = vlapic_trigger_lvt(vlapic, vector); - if (error) - break; } return (error); diff --git a/sys/amd64/vmm/vmm_stat.h b/sys/amd64/vmm/vmm_stat.h --- a/sys/amd64/vmm/vmm_stat.h +++ b/sys/amd64/vmm/vmm_stat.h @@ -45,7 +45,7 @@ }; struct vmm_stat_type; -typedef void (*vmm_stat_func_t)(struct vm *vm, int vcpu, +typedef void (*vmm_stat_func_t)(struct vcpu *vcpu, struct vmm_stat_type *stat); struct vmm_stat_type { @@ -87,7 +87,7 @@ void vmm_stat_init(void *vp); void vmm_stat_free(void *vp); -int vmm_stat_copy(struct vm *vm, int vcpu, int index, int count, +int vmm_stat_copy(struct vcpu *vcpu, int index, int count, int *num_stats, uint64_t *buf); int vmm_stat_desc_copy(int index, char *buf, int buflen); diff --git a/sys/amd64/vmm/vmm_stat.c b/sys/amd64/vmm/vmm_stat.c --- a/sys/amd64/vmm/vmm_stat.c +++ b/sys/amd64/vmm/vmm_stat.c @@ -82,16 +82,13 @@ } int -vmm_stat_copy(struct vm *vm, int vcpu, int index, int count, int *num_stats, +vmm_stat_copy(struct vcpu *vcpu, int index, int count, int *num_stats, uint64_t *buf) { struct vmm_stat_type *vst; uint64_t *stats; int i, tocopy; - if (vcpu < 0 || vcpu >= vm_get_maxcpus(vm)) - return (EINVAL); - if (index < 0 || count < 0) return (EINVAL); @@ -109,11 +106,11 @@ for (i = 0; i < vst_num_types; i++) { vst = vsttab[i]; if (vst->func != NULL) - (*vst->func)(vm, vcpu, vst); + (*vst->func)(vcpu, vst); } /* Copy over the stats */ - stats = vcpu_stats(vm_vcpu(vm, vcpu)); + stats = vcpu_stats(vcpu); memcpy(buf, stats + index, tocopy * sizeof(stats[0])); *num_stats = tocopy; return (0); diff --git a/sys/amd64/vmm/x86.c b/sys/amd64/vmm/x86.c --- a/sys/amd64/vmm/x86.c +++ b/sys/amd64/vmm/x86.c @@ -204,7 +204,7 @@ regs[2] &= ~AMDID2_MWAITX; /* Advertise RDTSCP if it is enabled. */ - error = vm_get_capability(vm, vcpu_id, + error = vm_get_capability(vcpu, VM_CAP_RDTSCP, &enable_rdtscp); if (error == 0 && enable_rdtscp) regs[3] |= AMDID_RDTSCP; @@ -311,7 +311,7 @@ case CPUID_0000_0001: do_cpuid(1, regs); - error = vm_get_x2apic_state(vm, vcpu_id, &x2apic_state); + error = vm_get_x2apic_state(vcpu, &x2apic_state); if (error) { panic("x86_emulate_cpuid: error %d " "fetching x2apic state", error); @@ -456,13 +456,13 @@ regs[3] &= CPUID_STDEXT3_MD_CLEAR; /* Advertise RDPID if it is enabled. */ - error = vm_get_capability(vm, vcpu_id, - VM_CAP_RDPID, &enable_rdpid); + error = vm_get_capability(vcpu, VM_CAP_RDPID, + &enable_rdpid); if (error == 0 && enable_rdpid) regs[2] |= CPUID_STDEXT2_RDPID; /* Advertise INVPCID if it is enabled. */ - error = vm_get_capability(vm, vcpu_id, + error = vm_get_capability(vcpu, VM_CAP_ENABLE_INVPCID, &enable_invpcid); if (error == 0 && enable_invpcid) regs[1] |= CPUID_STDEXT_INVPCID;