Ensure that register state is saved before it's used.
Without this there is a race where a physical CPU is still saving the
contents of registers into a vCPU buffer while another physical CPU
is already trying to restore the state.
Also adding test case that fails without this fix and succeeds with it.
Change-Id: I0badfd61f12385a3d8dc8d09eb298cfe56f2a415
diff --git a/src/cpu.c b/src/cpu.c
index 0f2bbba..1ae6cd1 100644
--- a/src/cpu.c
+++ b/src/cpu.c
@@ -96,8 +96,7 @@
if (!prev) {
struct vm *vm = vm_get(HF_PRIMARY_VM_ID);
struct vcpu *vcpu = &vm->vcpus[cpu_index(c)];
- arch_regs_init(&vcpu->regs, true, vm->id, vm->ptable.root,
- entry, arg);
+ arch_regs_set_pc_arg(&vcpu->regs, entry, arg);
vcpu_on(vcpu);
}
@@ -134,9 +133,11 @@
{
memset(vcpu, 0, sizeof(*vcpu));
sl_init(&vcpu->lock);
+ vcpu->regs_available = true;
vcpu->vm = vm;
vcpu->state = vcpu_state_off;
- arch_regs_set_vcpu_index(&vcpu->regs, vcpu - vm->vcpus);
+ arch_regs_init(&vcpu->regs, vm->id == HF_PRIMARY_VM_ID, vm->id,
+ vm->ptable.root, vcpu_index(vcpu));
}
void vcpu_on(struct vcpu *vcpu)