Introduce internal_interrupt_inject_locked
internal_interrupt_inject becomes a wrapper locking the target
vcpu and calling internal_interrupt_inject_locked.
Change-Id: Ib0133d77b0903168f0a1e3a0c8f958cc012ca9f4
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/src/api.c b/src/api.c
index 3370bcc..04c9de9 100644
--- a/src/api.c
+++ b/src/api.c
@@ -416,16 +416,14 @@
* - 1 if it was called by the primary VM and the primary VM now needs to wake
* up or kick the target vCPU.
*/
-static int64_t internal_interrupt_inject(struct vcpu *target_vcpu,
- uint32_t intid, struct vcpu *current,
- struct vcpu **next)
+static int64_t internal_interrupt_inject_locked(
+ struct vcpu_locked target_locked, uint32_t intid, struct vcpu *current,
+ struct vcpu **next)
{
uint32_t intid_index = intid / INTERRUPT_REGISTER_BITS;
uint32_t intid_mask = 1U << (intid % INTERRUPT_REGISTER_BITS);
int64_t ret = 0;
- sl_lock(&target_vcpu->lock);
-
/*
* We only need to change state and (maybe) trigger a virtual IRQ if it
* is enabled and was not previously pending. Otherwise we can skip
@@ -434,20 +432,20 @@
* If you change this logic make sure to update the need_vm_lock logic
* above to match.
*/
- if (!(target_vcpu->interrupts.interrupt_enabled[intid_index] &
- ~target_vcpu->interrupts.interrupt_pending[intid_index] &
+ if (!(target_locked.vcpu->interrupts.interrupt_enabled[intid_index] &
+ ~target_locked.vcpu->interrupts.interrupt_pending[intid_index] &
intid_mask)) {
goto out;
}
/* Increment the count. */
- target_vcpu->interrupts.enabled_and_pending_count++;
+ target_locked.vcpu->interrupts.enabled_and_pending_count++;
/*
* Only need to update state if there was not already an
* interrupt enabled and pending.
*/
- if (target_vcpu->interrupts.enabled_and_pending_count != 1) {
+ if (target_locked.vcpu->interrupts.enabled_and_pending_count != 1) {
goto out;
}
@@ -457,15 +455,30 @@
* should run or kick the target vCPU.
*/
ret = 1;
- } else if (current != target_vcpu && next != NULL) {
- *next = api_wake_up(current, target_vcpu);
+ } else if (current != target_locked.vcpu && next != NULL) {
+ *next = api_wake_up(current, target_locked.vcpu);
}
out:
/* Either way, make it pending. */
- target_vcpu->interrupts.interrupt_pending[intid_index] |= intid_mask;
+ target_locked.vcpu->interrupts.interrupt_pending[intid_index] |=
+ intid_mask;
- sl_unlock(&target_vcpu->lock);
+ return ret;
+}
+
+/* Wrapper to internal_interrupt_inject with locking of target vCPU */
+static int64_t internal_interrupt_inject(struct vcpu *target_vcpu,
+ uint32_t intid, struct vcpu *current,
+ struct vcpu **next)
+{
+ int64_t ret;
+ struct vcpu_locked target_locked;
+
+ target_locked = vcpu_lock(target_vcpu);
+ ret = internal_interrupt_inject_locked(target_locked, intid, current,
+ next);
+ vcpu_unlock(&target_locked);
return ret;
}