Fix race with checking remaining time on VM timer.

We were assuming that the remaining time on the timer could not be 0
if it had previously been checked not to be pending, but that could
have changed due to time passing since that check was made. To fix
this we get the remaining time once and treat the timer as pending if
the timer is enabled and the remaining time is 0.

Bug: 141469322
Change-Id: I3736a4c1a02acea46e55ce6c41f99e95e42711c0
diff --git a/src/api.c b/src/api.c
index 6f118a2..7a16436 100644
--- a/src/api.c
+++ b/src/api.c
@@ -465,28 +465,29 @@
 			break;
 		}
 
-		/* The timer expired so allow the interrupt to be delivered. */
-		if (arch_timer_pending(&vcpu->regs)) {
-			break;
-		}
-
-		/*
-		 * The vCPU is not ready to run, return the appropriate code to
-		 * the primary which called vcpu_run.
-		 */
 		if (arch_timer_enabled(&vcpu->regs)) {
+			uint64_t timer_remaining_ns =
+				arch_timer_remaining_ns(&vcpu->regs);
+
+			/*
+			 * The timer expired so allow the interrupt to be
+			 * delivered.
+			 */
+			if (timer_remaining_ns == 0) {
+				break;
+			}
+
+			/*
+			 * The vCPU is not ready to run, return the appropriate
+			 * code to the primary which called vcpu_run.
+			 */
 			run_ret->func =
 				vcpu->state == VCPU_STATE_BLOCKED_MAILBOX
 					? SPCI_MSG_WAIT_32
 					: HF_SPCI_RUN_WAIT_FOR_INTERRUPT;
 			run_ret->arg1 = ((uint32_t)vcpu_index(vcpu) << 16) |
 					vcpu->vm->id;
-			/*
-			 * arch_timer_remaining_ns should never return 0,
-			 * because if it would then arch_timer_pending would
-			 * have returned true before and so we won't get here.
-			 */
-			run_ret->arg2 = arch_timer_remaining_ns(&vcpu->regs);
+			run_ret->arg2 = timer_remaining_ns;
 		}
 
 		ret = false;