Lock vCPU when accessing enabled_and_pending_count.
Change-Id: Ic71d89c3b7a8acec71ac593228219e4044e58664
diff --git a/src/api.c b/src/api.c
index b3cab1a..081865e 100644
--- a/src/api.c
+++ b/src/api.c
@@ -1016,6 +1016,27 @@
}
/**
+ * Checks whether the vCPU's attempt to block for a message has already been
+ * interrupted or whether it is allowed to block.
+ */
+bool api_spci_msg_recv_block_interrupted(struct vcpu *current)
+{
+ bool interrupted;
+
+ sl_lock(¤t->lock);
+
+ /*
+ * Don't block if there are enabled and pending interrupts, to match
+ * behaviour of wait_for_interrupt.
+ */
+ interrupted = (current->interrupts.enabled_and_pending_count > 0);
+
+ sl_unlock(¤t->lock);
+
+ return interrupted;
+}
+
+/**
* Receives a message from the mailbox. If one isn't available, this function
* can optionally block the caller until one becomes available.
*
@@ -1058,12 +1079,7 @@
* that time to SPCI_SUCCESS.
*/
return_code = SPCI_INTERRUPTED;
-
- /*
- * Don't block if there are enabled and pending interrupts, to match
- * behaviour of wait_for_interrupt.
- */
- if (current->interrupts.enabled_and_pending_count > 0) {
+ if (api_spci_msg_recv_block_interrupted(current)) {
goto out;
}
diff --git a/src/arch/aarch64/hypervisor/handler.c b/src/arch/aarch64/hypervisor/handler.c
index 621b847..0658051 100644
--- a/src/arch/aarch64/hypervisor/handler.c
+++ b/src/arch/aarch64/hypervisor/handler.c
@@ -391,16 +391,22 @@
* Not switching vCPUs, set the bit for the current vCPU
* directly in the register.
*/
+ struct vcpu *vcpu = current();
+
+ sl_lock(&vcpu->lock);
set_virtual_interrupt_current(
- current()->interrupts.enabled_and_pending_count > 0);
+ vcpu->interrupts.enabled_and_pending_count > 0);
+ sl_unlock(&vcpu->lock);
} else {
/*
* About to switch vCPUs, set the bit for the vCPU to which we
* are switching in the saved copy of the register.
*/
+ sl_lock(&ret.new->lock);
set_virtual_interrupt(
&ret.new->regs,
ret.new->interrupts.enabled_and_pending_count > 0);
+ sl_unlock(&ret.new->lock);
}
return ret;