Making timer test slightly more permissive.
It was failing on FVP with the TLB invalidation change, due to a race
condition.
Bug: 132422393
Change-Id: Ib0bb5ecf408cf020aa6cb9160fbc0eb7174a6c1c
diff --git a/test/vmapi/gicv3/timer_secondary.c b/test/vmapi/gicv3/timer_secondary.c
index df73e57..849101b 100644
--- a/test/vmapi/gicv3/timer_secondary.c
+++ b/test/vmapi/gicv3/timer_secondary.c
@@ -114,46 +114,60 @@
HF_PRIMARY_VM_ID);
EXPECT_EQ(spci_msg_send(0), 0);
- /*
- * Let the secondary handle the message and set the timer. Then there's
- * a race for whether it manages to block and switch to the primary
- * before the hardware timer fires, so we need to handle both cases.
- */
+ /* Let the secondary handle the message and set the timer. */
last_interrupt_id = 0;
run_res = hf_vcpu_run(SERVICE_VM0, 0);
- if (run_res.code == expected_code) {
+
+ /*
+ * There's a race for whether the secondary manages to block and switch
+ * to the primary before the hardware timer fires, so we need to handle
+ * three cases:
+ * 1. The (hardware) timer fires immediately, we get
+ * HF_VCPU_RUN_PREEMPTED.
+ * 2. The secondary blocks and switches back, we get expected_code until
+ * the timer fires.
+ * 2a. The timer then expires while we are in the primary, so Hafnium
+ * can inject the timer interrupt the next time we call hf_vcpu_run.
+ * 2b. The timer fires while the secondary is running, so we get
+ * HF_VCPU_RUN_PREEMPTED as in case 1.
+ */
+
+ if (run_res.code != expected_code &&
+ run_res.code != HF_VCPU_RUN_PREEMPTED) {
+ FAIL("Expected run to return HF_VCPU_RUN_PREEMPTED or %d, but "
+ "got %d",
+ expected_code, run_res.code);
+ }
+
+ /* Loop until the timer fires. */
+ while (run_res.code == expected_code) {
/*
* This case happens if the secondary manages to block and
* switch to the primary before the timer fires.
*/
- dlog("secondary sleeping after receiving timer message\n");
- /* Loop until the timer fires. */
- while (run_res.code == expected_code) {
- dlog("Primary looping until timer fires\n");
- if (expected_code == HF_VCPU_RUN_WAIT_FOR_INTERRUPT ||
- expected_code == HF_VCPU_RUN_WAIT_FOR_MESSAGE) {
- EXPECT_NE(run_res.sleep.ns,
- HF_SLEEP_INDEFINITE);
- dlog("%d ns remaining\n", run_res.sleep.ns);
- }
- run_res = hf_vcpu_run(SERVICE_VM0, 0);
+ dlog("Primary looping until timer fires\n");
+ if (expected_code == HF_VCPU_RUN_WAIT_FOR_INTERRUPT ||
+ expected_code == HF_VCPU_RUN_WAIT_FOR_MESSAGE) {
+ EXPECT_NE(run_res.sleep.ns, HF_SLEEP_INDEFINITE);
+ dlog("%d ns remaining\n", run_res.sleep.ns);
}
- dlog("Primary done looping\n");
- } else if (run_res.code == HF_VCPU_RUN_PREEMPTED) {
+ run_res = hf_vcpu_run(SERVICE_VM0, 0);
+ }
+ dlog("Primary done looping\n");
+
+ if (run_res.code == HF_VCPU_RUN_PREEMPTED) {
/*
* This case happens if the (hardware) timer fires before the
- * secondary blocks and switches to the primary. Then we get the
- * interrupt to the primary, ignore it, and see a
- * HF_VCPU_RUN_PREEMPTED code from the hf_vcpu_run call, so we
+ * secondary blocks and switches to the primary, either
+ * immediately after setting the timer or during the loop above.
+ * Then we get the interrupt to the primary, ignore it, and see
+ * a HF_VCPU_RUN_PREEMPTED code from the hf_vcpu_run call, so we
* should call it again for the timer interrupt to be injected
* automatically by Hafnium.
*/
EXPECT_EQ(last_interrupt_id, VIRTUAL_TIMER_IRQ);
dlog("Preempted by timer interrupt, running again\n");
run_res = hf_vcpu_run(SERVICE_VM0, 0);
- } else {
- /* No other return codes should occur here, so fail. */
- FAIL("Unexpected run result code (%d).", run_res.code);
}
/* Once we wake it up it should get the timer interrupt and respond. */