aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2022-11-18 18:03:52 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2023-01-26 22:03:29 +0000
commit3348ba1d6da9fd64038770cc38f0651e6d085963 (patch)
treecf7bca46d9bdfe3a0e85ff0bf36445121844177f
parent197cb60d7af4e9bc2ba0b15bda24289111c87fe8 (diff)
downloadsrc-3348ba1d6da9fd64038770cc38f0651e6d085963.tar.gz
src-3348ba1d6da9fd64038770cc38f0651e6d085963.zip
vmm: Lookup vcpu pointers in vmmdev_ioctl.
Centralize mapping vCPU IDs to struct vcpu objects in vmmdev_ioctl and pass vcpu pointers to the routines in vmm.c. For operations that want to perform an action on all vCPUs or on a single vCPU, pass pointers to both the VM and the vCPU using a NULL vCPU pointer to request global actions. Reviewed by: corvink, markj Differential Revision: https://reviews.freebsd.org/D37168 (cherry picked from commit 3f0f4b1598e0e7005bebed7ea3458e96d0fb8e2f)
-rw-r--r--sys/amd64/include/vmm.h29
-rw-r--r--sys/amd64/vmm/io/vatpic.c2
-rw-r--r--sys/amd64/vmm/io/vlapic.c34
-rw-r--r--sys/amd64/vmm/vmm.c259
-rw-r--r--sys/amd64/vmm/vmm_dev.c108
-rw-r--r--sys/amd64/vmm/vmm_ioport.c19
-rw-r--r--sys/amd64/vmm/vmm_ioport.h2
-rw-r--r--sys/amd64/vmm/vmm_lapic.c34
-rw-r--r--sys/amd64/vmm/vmm_lapic.h12
-rw-r--r--sys/amd64/vmm/vmm_stat.c9
-rw-r--r--sys/amd64/vmm/vmm_stat.h4
-rw-r--r--sys/amd64/vmm/x86.c10
12 files changed, 245 insertions, 277 deletions
diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h
index b8f641910e4f..7c346d7ed4ed 100644
--- a/sys/amd64/include/vmm.h
+++ b/sys/amd64/include/vmm.h
@@ -264,14 +264,14 @@ int vm_get_register(struct vcpu *vcpu, int reg, uint64_t *retval);
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 vcpu *vm_vcpu(struct vm *vm, int cpu);
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 @@ enum vcpu_state {
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
@@ -386,7 +385,7 @@ vcpu_should_yield(struct vcpu *vcpu)
#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);
@@ -432,7 +431,7 @@ int vm_exit_intinfo(struct vcpu *vcpu, uint64_t intinfo);
*/
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
index 1d4ccfb9d0ca..5ece5d433244 100644
--- a/sys/amd64/vmm/io/vatpic.c
+++ b/sys/amd64/vmm/io/vatpic.c
@@ -262,7 +262,7 @@ vatpic_notify_intr(struct vatpic *vatpic)
* 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
index 664852260943..bcfe6b498721 100644
--- a/sys/amd64/vmm/io/vlapic.c
+++ b/sys/amd64/vmm/io/vlapic.c
@@ -460,13 +460,13 @@ vlapic_fire_lvt(struct vlapic *vlapic, u_int lvt)
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 @@ vlapic_trigger_lvt(struct vlapic *vlapic, int vector)
*/
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 @@ vlapic_icrlo_write_handler(struct vlapic *vlapic, bool *retu)
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 @@ vlapic_icrlo_write_handler(struct vlapic *vlapic, bool *retu)
}
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 @@ vlapic_icrlo_write_handler(struct vlapic *vlapic, bool *retu)
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 @@ vlapic_icrlo_write_handler(struct vlapic *vlapic, bool *retu)
* 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 @@ vlapic_icrlo_write_handler(struct vlapic *vlapic, bool *retu)
/*
* 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 @@ vlapic_icrlo_write_handler(struct vlapic *vlapic, bool *retu)
}
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 @@ vlapic_self_ipi_handler(struct vlapic *vlapic, uint64_t val)
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 @@ void
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_deliver_intr(struct vm *vm, bool level, uint32_t dest, bool phys,
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
index 2405a4450072..825b3383b787 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -309,12 +309,6 @@ vcpu_state2str(enum vcpu_state state)
}
#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_init(struct vm *vm, int vcpu_id, bool create)
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 @@ vm_get_seg_desc(struct vcpu *vcpu, int reg, struct seg_desc *desc)
}
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 @@ save_guest_fpustate(struct vcpu *vcpu)
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 @@ vcpu_set_state_locked(struct vm *vm, int vcpuid, enum vcpu_state newstate,
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 @@ vcpu_set_state_locked(struct vm *vm, int vcpuid, enum vcpu_state newstate,
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 @@ vcpu_set_state_locked(struct vm *vm, int vcpuid, enum vcpu_state newstate,
}
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 @@ vm_handle_rendezvous(struct vcpu *vcpu)
* 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 @@ vm_handle_hlt(struct vm *vm, int vcpuid, bool intr_disabled, bool *retu)
*/
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 @@ vm_handle_hlt(struct vm *vm, int vcpuid, bool intr_disabled, bool *retu)
}
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->td_flags & TDF_NEEDSUSPCHK) != 0) {
vcpu_unlock(vcpu);
@@ -1466,14 +1455,13 @@ vm_handle_hlt(struct vm *vm, int vcpuid, bool intr_disabled, bool *retu)
}
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 @@ vm_handle_paging(struct vm *vm, int vcpuid, bool *retu)
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 @@ vm_handle_paging(struct vm *vm, int vcpuid, bool *retu)
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 @@ done:
}
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 @@ vm_handle_inst_emul(struct vm *vm, int vcpuid, bool *retu)
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 @@ vm_handle_inst_emul(struct vm *vm, int vcpuid, bool *retu)
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 @@ vm_handle_inst_emul(struct vm *vm, int vcpuid, bool *retu)
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 @@ vm_handle_inst_emul(struct vm *vm, int vcpuid, bool *retu)
*/
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 @@ vm_handle_inst_emul(struct vm *vm, int vcpuid, bool *retu)
}
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 @@ vm_handle_suspend(struct vm *vm, int vcpuid, bool *retu)
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->td_flags & TDF_NEEDSUSPCHK) != 0) {
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 @@ vm_handle_suspend(struct vm *vm, int vcpuid, bool *retu)
*/
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 @@ vm_handle_suspend(struct vm *vm, int vcpuid, bool *retu)
}
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 @@ vm_suspend(struct vm *vm, enum vm_suspend_how how)
*/
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);
@@ -1748,21 +1731,18 @@ vm_exit_astpending(struct vcpu *vcpu, uint64_t rip)
}
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);
@@ -1771,7 +1751,6 @@ vm_run(struct vm *vm, struct vm_run *vmrun)
return (EINVAL);
pmap = vmspace_pmap(vm->vmspace);
- vcpu = &vm->vcpu[vcpuid];
vme = &vcpu->exitinfo;
evinfo.rptr = &vm->rendezvous_func;
evinfo.sptr = &vm->suspend;
@@ -1789,9 +1768,9 @@ restart:
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);
@@ -1804,10 +1783,10 @@ restart:
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);
@@ -1817,17 +1796,17 @@ restart:
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:
@@ -1853,10 +1832,10 @@ restart:
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);
}
@@ -2068,14 +2047,8 @@ vm_entry_intinfo(struct vcpu *vcpu, uint64_t *retinfo)
}
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);
@@ -2165,17 +2138,11 @@ vm_inject_pf(struct vcpu *vcpu, int error_code, uint64_t cr2)
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);
}
@@ -2198,17 +2165,11 @@ vm_nmi_clear(struct vcpu *vcpu)
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);
}
@@ -2229,27 +2190,21 @@ vm_extint_clear(struct vcpu *vcpu)
}
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 *
@@ -2340,19 +2295,12 @@ vm_iommu_domain(struct vm *vm)
}
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);
@@ -2373,58 +2321,48 @@ vcpu_get_state(struct vcpu *vcpu, int *hostcpu)
}
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);
}
@@ -2465,28 +2403,19 @@ vcpu_stats(struct vcpu *vcpu)
}
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);
@@ -2533,10 +2462,8 @@ vcpu_notify_event_locked(struct vcpu *vcpu, bool lapic_intr)
}
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);
@@ -2575,7 +2502,7 @@ restart:
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");
@@ -2601,7 +2528,7 @@ restart:
*/
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));
@@ -2748,22 +2675,22 @@ VMM_STAT_DECLARE(VMM_MEM_RESIDENT);
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
index 1d36e190c7a6..a007a25aa9b5 100644
--- a/sys/amd64/vmm/vmm_dev.c
+++ b/sys/amd64/vmm/vmm_dev.c
@@ -131,22 +131,24 @@ vcpu_lock_one(struct vmmdev_softc *sc, int vcpu)
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 @@ vm_set_register_set(struct vcpu *vcpu, unsigned int count, int *regnum,
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 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
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 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
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 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
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 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
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 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
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 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
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 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
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 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
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 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
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 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
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 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
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 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
("%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 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
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 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
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.c b/sys/amd64/vmm/vmm_ioport.c
index 50c02378a4c5..24c556a3c8ae 100644
--- a/sys/amd64/vmm/vmm_ioport.c
+++ b/sys/amd64/vmm/vmm_ioport.c
@@ -100,8 +100,7 @@ inout_instruction(struct vm_exit *vmexit)
#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 @@ emulate_inout_port(struct vm *vm, int vcpuid, struct vm_exit *vmexit,
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 @@ emulate_inout_port(struct vm *vm, int vcpuid, struct vm_exit *vmexit,
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 @@ emulate_inout_port(struct vm *vm, int vcpuid, struct vm_exit *vmexit,
}
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(struct vm *vm, int vcpuid, struct vm_exit *vmexit, bool *retu)
("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_ioport.h b/sys/amd64/vmm/vmm_ioport.h
index fd20ecfd5e94..0b6f09f01e9a 100644
--- 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_lapic.c b/sys/amd64/vmm/vmm_lapic.c
index ae4205e11614..1b6c51c8283c 100644
--- a/sys/amd64/vmm/vmm_lapic.c
+++ b/sys/amd64/vmm/vmm_lapic.c
@@ -52,13 +52,10 @@ __FBSDID("$FreeBSD$");
#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 @@ lapic_set_intr(struct vm *vm, int cpu, int vector, bool level)
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_lapic.h b/sys/amd64/vmm/vmm_lapic.h
index e917fd50a69d..a361cd09c332 100644
--- a/sys/amd64/vmm/vmm_lapic.h
+++ b/sys/amd64/vmm/vmm_lapic.h
@@ -47,29 +47,29 @@ int lapic_mmio_write(struct vcpu *vcpu, uint64_t gpa,
* 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_stat.c b/sys/amd64/vmm/vmm_stat.c
index b317f5679bf3..2df4423bc60f 100644
--- a/sys/amd64/vmm/vmm_stat.c
+++ b/sys/amd64/vmm/vmm_stat.c
@@ -82,16 +82,13 @@ vmm_stat_register(void *arg)
}
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 @@ vmm_stat_copy(struct vm *vm, int vcpu, int index, int count, int *num_stats,
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/vmm_stat.h b/sys/amd64/vmm/vmm_stat.h
index 69e7b9367686..e40a960ec82a 100644
--- a/sys/amd64/vmm/vmm_stat.h
+++ b/sys/amd64/vmm/vmm_stat.h
@@ -45,7 +45,7 @@ enum vmm_stat_scope {
};
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_alloc(void);
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/x86.c b/sys/amd64/vmm/x86.c
index 9a4bb049e4c9..d99fb391afba 100644
--- a/sys/amd64/vmm/x86.c
+++ b/sys/amd64/vmm/x86.c
@@ -204,7 +204,7 @@ x86_emulate_cpuid(struct vcpu *vcpu, uint64_t *rax, uint64_t *rbx,
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 @@ x86_emulate_cpuid(struct vcpu *vcpu, uint64_t *rax, uint64_t *rbx,
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 @@ x86_emulate_cpuid(struct vcpu *vcpu, uint64_t *rax, uint64_t *rbx,
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;