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 @@ -329,7 +329,9 @@ cpuset_t vm_active_cpus(struct vm *vm); cpuset_t vm_debug_cpus(struct vm *vm); cpuset_t vm_suspended_cpus(struct vm *vm); +bool vm_start_single_cpu(struct vm *vm, struct vcpu *vcpu); cpuset_t vm_start_cpus(struct vm *vm, const cpuset_t *tostart); +void vm_await_start_single_cpu(struct vm *vm, struct vcpu *vcpu); void vm_await_start(struct vm *vm, const cpuset_t *waiting); #endif /* _SYS__CPUSET_H_ */ 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 @@ -1128,8 +1128,9 @@ break; /* vCPU i is waiting for SIPI. */ - CPU_SETOF(i, &dmask); - vm_await_start(vlapic->vm, &dmask); + vm_await_start_single_cpu(vlapic->vm, + vm_vcpu(vlapic->vm, i)); + break; } @@ -1152,10 +1153,10 @@ /* * Ignore SIPIs in any state other than wait-for-SIPI */ - CPU_SETOF(i, &dmask); - dmask = vm_start_cpus(vlapic->vm, &dmask); - if (CPU_EMPTY(&dmask)) + if (vm_start_single_cpu(vlapic->vm, + vm_vcpu(vlapic->vm, i))) { break; + } vmexit = vm_exitinfo(vlapic->vcpu); vmexit->exitcode = VM_EXITCODE_SPINUP_AP; @@ -1166,10 +1167,7 @@ break; } - /* - * Ignore SIPIs in any state other than wait-for-SIPI - */ - ipimask = vm_start_cpus(vlapic->vm, &dmask); + ipimask = dmask; break; default: return (1); @@ -1207,6 +1205,13 @@ vm_await_start(vcpu_vm(vcpu), &vme->u.ipi.dmask); break; case APIC_DELMODE_STARTUP: + /* + * Ignore SIPIs in any state other than wait-for-SIPI + */ + vme->u.ipi.dmask = vm_start_cpus(vcpu_vm(vcpu), &vme->u.ipi.dmask); + if (CPU_EMPTY(&vme->u.ipi.dmask)) { + *retu = false; + } break; default: return (1); 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 @@ -2496,6 +2496,12 @@ return (vm->suspended_cpus); } +bool +vm_start_single_cpu(struct vm *vm, struct vcpu *vcpu) +{ + return (CPU_TEST_CLR_ATOMIC(vcpu->vcpuid, &vm->startup_cpus)); +} + /* * Returns the subset of vCPUs in tostart that are awaiting startup. * These vCPUs are also marked as no longer awaiting startup. @@ -2512,6 +2518,12 @@ return (set); } +void +vm_await_start_single_cpu(struct vm *vm, struct vcpu *vcpu) +{ + CPU_SET_ATOMIC(vcpu->vcpuid, &vm->startup_cpus); +} + void vm_await_start(struct vm *vm, const cpuset_t *waiting) { diff --git a/sys/sys/cpuset.h b/sys/sys/cpuset.h --- a/sys/sys/cpuset.h +++ b/sys/sys/cpuset.h @@ -64,6 +64,8 @@ #define CPU_CLR_ATOMIC(n, p) __BIT_CLR_ATOMIC(CPU_SETSIZE, n, p) #define CPU_SET_ATOMIC(n, p) __BIT_SET_ATOMIC(CPU_SETSIZE, n, p) #define CPU_SET_ATOMIC_ACQ(n, p) __BIT_SET_ATOMIC_ACQ(CPU_SETSIZE, n, p) +#define CPU_TEST_CLR_ATOMIC(n, p) __BIT_TEST_CLR_ATOMIC(CPU_SETSIZE, n, p) +#define CPU_TEST_SET_ATOMIC(n, p) __BIT_TEST_SET_ATOMIC(CPU_SETSIZE, n, p) #define CPU_AND_ATOMIC(n, p) __BIT_AND_ATOMIC(CPU_SETSIZE, n, p) #define CPU_OR_ATOMIC(d, s) __BIT_OR_ATOMIC(CPU_SETSIZE, d, s) #define CPU_COPY_STORE_REL(f, t) __BIT_COPY_STORE_REL(CPU_SETSIZE, f, t)