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/inc/hf/cpu.h b/inc/hf/cpu.h
index 76d71d6..b477dec 100644
--- a/inc/hf/cpu.h
+++ b/inc/hf/cpu.h
@@ -54,6 +54,11 @@
uint32_t interrupt_pending[HF_NUM_INTIDS / INTERRUPT_REGISTER_BITS];
};
+struct retval_state {
+ uintptr_t value;
+ bool force;
+};
+
struct vcpu {
struct spinlock lock;
enum vcpu_state state;
@@ -62,6 +67,20 @@
struct vcpu *mailbox_next;
struct arch_regs regs;
struct interrupts interrupts;
+
+ /*
+ * The following field is used to force a return value to be set the
+ * next time a vCPU belonging to a secondary VM runs. For primary VMs,
+ * 'regs' can be set directly.
+ */
+ struct retval_state retval;
+
+ /*
+ * Determine whether the 'regs' field is available for use. This is set
+ * to false when a vCPU is about to run on a physical CPU, and is set
+ * back to true when it is descheduled.
+ */
+ bool regs_available;
};
/* TODO: Update alignment such that cpus are in different cache lines. */