summaryrefslogtreecommitdiff
path: root/tests/runtime_services
diff options
context:
space:
mode:
authorYatharth Kochar <yatharth.kochar@arm.com>2016-07-26 16:51:58 +0100
committerSoby Mathew <soby.mathew@arm.com>2016-09-28 15:00:12 +0100
commitf168961e3a42107a3cbcdc9d042b53f732a03756 (patch)
treea7c1f30909a259005ba64ed5a17a63cf748ade52 /tests/runtime_services
parent7ed333d5eaecf4ad940d41bca3dee9c83e7bc822 (diff)
Prevent timer interrupts firing prior to cpu suspend
Usually for CPU suspend tests, the timer is programmed to wakeup the CPU from suspend. There is a chance that this timer interrupt might fire before the PSCI CPU suspend call is made. If this happens, the interrupt handler for the timer in TFTF will execute and clear the interrupt and thus the CPU will not wakeup from suspend. This patch solves this problem in 2 ways: 1. By replacing usage of `tftf_program_timer()` and `tftf_cpu_suspend()` with `tftf_program_timer_and_suspend`. This solution works in cases the error code from PSCI CPU suspend is not needed. 2. If the error code from PSCI CPU suspend is required by the test case, then the interrupt is disabled prior to timer programming and reenabled after return from suspend. Change-Id: Ic9d53126fb4c1ef214ddf855a994785e02ea3e4f
Diffstat (limited to 'tests/runtime_services')
-rw-r--r--tests/runtime_services/standard_service/psci/api_tests/cpu_suspend/test_suspend.c46
-rw-r--r--tests/runtime_services/standard_service/psci/system_tests/test_psci_on_off_suspend_stress.c34
2 files changed, 52 insertions, 28 deletions
diff --git a/tests/runtime_services/standard_service/psci/api_tests/cpu_suspend/test_suspend.c b/tests/runtime_services/standard_service/psci/api_tests/cpu_suspend/test_suspend.c
index 4beae61..eceb1e9 100644
--- a/tests/runtime_services/standard_service/psci/api_tests/cpu_suspend/test_suspend.c
+++ b/tests/runtime_services/standard_service/psci/api_tests/cpu_suspend/test_suspend.c
@@ -31,6 +31,7 @@
#include <arch.h>
#include <arch_helpers.h>
#include <assert.h>
+#include <debug.h>
#include <events.h>
#include <irq.h>
#include <plat_topology.h>
@@ -89,13 +90,27 @@ static test_result_t suspend_non_lead_cpu(void)
unsigned int core_pos = platform_get_core_pos(mpid);
uint32_t power_state, stateid;
int rc, expected_return_val;
+ u_register_t flags;
tftf_timer_register_handler(requested_irq_handler);
/* Tell the lead CPU that the calling CPU is about to suspend itself */
tftf_send_event(&cpu_ready[core_pos]);
- tftf_program_timer(PLAT_SUSPEND_ENTRY_TIME);
+ /* IRQs need to be disabled prior to programming the timer */
+ /* Preserve DAIF flags*/
+ flags = read_daif();
+ disable_irq();
+ isb();
+
+ rc = tftf_program_timer(PLAT_SUSPEND_ENTRY_TIME);
+ if (rc != 0) {
+ /* Restore previous DAIF flags */
+ write_daif(flags);
+ isb();
+ ERROR("Timer programming failed with error %d\n", rc);
+ return TEST_RESULT_FAIL;
+ }
expected_return_val = tftf_psci_make_composite_state_id(test_aff_level,
test_suspend_type, &stateid);
@@ -106,9 +121,12 @@ static test_result_t suspend_non_lead_cpu(void)
power_state = tftf_make_psci_pstate(test_aff_level,
test_suspend_type,
stateid);
-
rc = tftf_cpu_suspend(power_state);
+ /* Restore previous DAIF flags */
+ write_daif(flags);
+ isb();
+
/* Wait until the IRQ wake interrupt is received */
while (!ACCESS(requested_irq_received[core_pos]))
;
@@ -141,6 +159,7 @@ static test_result_t test_psci_suspend(unsigned int aff_level,
unsigned int core_pos;
uint32_t power_state, stateid;
int rc, expected_return_val;
+ u_register_t flags;
if (aff_level > MPIDR_MAX_AFFLVL)
return TEST_RESULT_SKIPPED;
@@ -195,11 +214,24 @@ static test_result_t test_psci_suspend(unsigned int aff_level,
tftf_wait_for_event(&cpu_ready[core_pos]);
}
+ /* IRQs need to be disabled prior to programming the timer */
+ /* Preserve DAIF flags*/
+ flags = read_daif();
+ disable_irq();
+ isb();
+
/*
- * Program the timer, this will serve as the wake-up event to come
- * out of suspend state
+ * Program the timer, this will serve as the
+ * wake-up event to come out of suspend state.
*/
- tftf_program_timer(PLAT_SUSPEND_ENTRY_TIME);
+ rc = tftf_program_timer(PLAT_SUSPEND_ENTRY_TIME);
+ if (rc) {
+ /* Restore previous DAIF flags */
+ write_daif(flags);
+ isb();
+ ERROR("Timer programming failed with error %d\n", rc);
+ return TEST_RESULT_FAIL;
+ }
expected_return_val = tftf_psci_make_composite_state_id(test_aff_level,
test_suspend_type, &stateid);
@@ -215,6 +247,10 @@ static test_result_t test_psci_suspend(unsigned int aff_level,
else
rc = tftf_cpu_suspend(power_state);
+ /* Restore previous DAIF flags */
+ write_daif(flags);
+ isb();
+
/*
* Cancel the timer set up by lead CPU in case we have returned early
* due to invalid parameters or it will lead to spurious wake-up later.
diff --git a/tests/runtime_services/standard_service/psci/system_tests/test_psci_on_off_suspend_stress.c b/tests/runtime_services/standard_service/psci/system_tests/test_psci_on_off_suspend_stress.c
index 7d8c04f..8051c61 100644
--- a/tests/runtime_services/standard_service/psci/system_tests/test_psci_on_off_suspend_stress.c
+++ b/tests/runtime_services/standard_service/psci/system_tests/test_psci_on_off_suspend_stress.c
@@ -163,16 +163,10 @@ static test_result_t random_suspend_off_loop(void)
return TEST_RESULT_SUCCESS;
/* Program timer for wake-up event. */
- rc = tftf_program_timer(PLAT_SUSPEND_ENTRY_TIME);
- if (rc) {
- tftf_testcase_printf("tftf_program_timer error"
- " 0x%x\n", rc);
- return TEST_RESULT_FAIL;
- }
-
- rc = tftf_cpu_suspend(power_state);
+ rc = tftf_program_timer_and_suspend(PLAT_SUSPEND_ENTRY_TIME,
+ power_state);
if (rc != PSCI_E_SUCCESS) {
- tftf_testcase_printf("CPU suspend returned error"
+ tftf_testcase_printf("CPU timer/suspend returned error"
" 0x%x\n", rc);
return TEST_RESULT_FAIL;
}
@@ -193,17 +187,11 @@ static test_result_t lead_cpu_main(unsigned long long mpid)
return TEST_RESULT_FAIL;
/* Program timer for wake-up event. */
- rc = tftf_program_timer(PLAT_SUSPEND_ENTRY_TIME);
- if (rc) {
- tftf_testcase_printf("tftf_program_timer error 0x%x\n",
- rc);
- return TEST_RESULT_FAIL;
- }
-
- rc = tftf_cpu_suspend(power_state);
+ rc = tftf_program_timer_and_suspend(PLAT_SUSPEND_ENTRY_TIME,
+ power_state);
if (rc != PSCI_E_SUCCESS) {
- tftf_testcase_printf("CPU suspend returned error"
- " 0x%x\n", rc);
+ tftf_testcase_printf("CPU timer/suspend returned error"
+ " 0x%x\n", rc);
return TEST_RESULT_FAIL;
}
@@ -516,11 +504,11 @@ static test_result_t launch_cpu_on_off_stress(void)
/* Check whether to suspend before iterating */
if (include_cpu_suspend) {
- tftf_program_timer(PLAT_SUSPEND_ENTRY_TIME);
- ret = tftf_cpu_suspend(power_state);
+ ret = tftf_program_timer_and_suspend(
+ PLAT_SUSPEND_ENTRY_TIME, power_state);
if (ret != PSCI_E_SUCCESS) {
- tftf_testcase_printf("suspend error = 0x%x \n",
- ret);
+ tftf_testcase_printf("CPU timer/suspend"
+ " returned error 0x%x\n", ret);
return TEST_RESULT_FAIL;
}
}