blob: 8799aa5f0d6a17cacbd4705834bafaa9061f8dd3 [file] [log] [blame]
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +02001/*
2 * Copyright (c) 2018, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <amu.h>
8#include <arch.h>
9#include <arch_helpers.h>
10#include <assert.h>
11#include <debug.h>
12#include <irq.h>
13#include <plat_topology.h>
14#include <platform.h>
15#include <power_management.h>
16#include <tftf_lib.h>
17#include <timer.h>
18
19#define SUSPEND_TIME_1_SEC 1000
20
21static volatile int wakeup_irq_received[PLATFORM_CORE_COUNT];
22
23/* Dummy timer handler that sets a flag to check it has been called. */
24static int suspend_wakeup_handler(void *data)
25{
26 u_register_t core_mpid = read_mpidr_el1() & MPID_MASK;
27 unsigned int core_pos = platform_get_core_pos(core_mpid);
28
29 assert(wakeup_irq_received[core_pos] == 0);
30
31 wakeup_irq_received[core_pos] = 1;
32
33 return 0;
34}
35
36/*
37 * Helper function to suspend a CPU to power level 0 and wake it up with
38 * a timer.
39 */
40static test_result_t suspend_and_resume_this_cpu(void)
41{
42 uint32_t stateid;
43 int psci_ret;
44 test_result_t result = TEST_RESULT_SUCCESS;
45
46 u_register_t core_mpid = read_mpidr_el1() & MPID_MASK;
47 unsigned int core_pos = platform_get_core_pos(core_mpid);
48
49 /* Prepare wakeup timer. IRQs need to be enabled. */
50 wakeup_irq_received[core_pos] = 0;
51
52 tftf_timer_register_handler(suspend_wakeup_handler);
53
54 /* Program timer to fire interrupt after timer expires */
55 tftf_program_timer(SUSPEND_TIME_1_SEC);
56
57 /*
58 * Suspend the calling CPU to power level 0 and power
59 * state.
60 */
61 psci_ret = tftf_psci_make_composite_state_id(PSTATE_AFF_LVL_0,
62 PSTATE_TYPE_POWERDOWN,
63 &stateid);
64 if (psci_ret != PSCI_E_SUCCESS) {
65 mp_printf("Failed to make composite state ID @ CPU %d. rc = %x\n",
66 core_pos, psci_ret);
67 result = TEST_RESULT_FAIL;
68 } else {
69 unsigned int power_state = tftf_make_psci_pstate(PSTATE_AFF_LVL_0,
70 PSTATE_TYPE_POWERDOWN, stateid);
71 psci_ret = tftf_cpu_suspend(power_state);
72
73 if (!wakeup_irq_received[core_pos]) {
74 mp_printf("Didn't receive wakeup IRQ in CPU %d.\n",
75 core_pos);
76 result = TEST_RESULT_FAIL;
77 }
78
79 if (psci_ret != PSCI_E_SUCCESS) {
80 mp_printf("Failed to suspend from CPU %d. ret: %x\n",
81 core_pos, psci_ret);
82 result = TEST_RESULT_FAIL;
83 }
84 }
85
86 /* Wake up. Remove timer after waking up.*/
87 tftf_cancel_timer();
88 tftf_timer_unregister_handler();
89
90 return result;
91}
92
93/*
John Tsichritziscae91ca2019-05-12 16:06:09 +010094 * Helper function that checks whether the value of a group0 counter is valid
95 * or not. The first 3 counters (0,1,2) cannot have values of zero but the last
96 * counter that counts "memory stall cycles" can have a value of zero, under
97 * certain circumstances.
98 *
99 * Return values:
100 * 0 = valid counter value
101 * -1 = invalid counter value
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200102 */
John Tsichritziscae91ca2019-05-12 16:06:09 +0100103static int amu_group0_cnt_valid(unsigned int idx, uint64_t value)
104{
105 int answer = 0;
106
107 if ((idx <= 2) && (value == 0))
108 answer = -1;
109
110 return answer;
111}
112
113/*
114 * Check that group0 counters are valid. As EL3 has enabled the counters before
115 * the first entry to NS world, the counters should have increased by the time
116 * we reach this test case.
117 */
118test_result_t test_amu_valid_ctr(void)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200119{
120 int i;
121
122 if (!amu_supported())
123 return TEST_RESULT_SKIPPED;
124
125 /* If counters are not enabled, then skip the test */
John Tsichritzis68759a82019-05-12 15:10:27 +0100126 if (read_amcntenset0_el0() != AMU_GROUP0_COUNTERS_MASK)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200127 return TEST_RESULT_SKIPPED;
128
129 for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++) {
John Tsichritziscae91ca2019-05-12 16:06:09 +0100130 uint64_t value;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200131
John Tsichritziscae91ca2019-05-12 16:06:09 +0100132 value = amu_group0_cnt_read(i);
133 if (amu_group0_cnt_valid(i, value)) {
134 tftf_testcase_printf("Group0 counter %d has invalid value %lld\n", i, value);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200135 return TEST_RESULT_FAIL;
136 }
137 }
138
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200139 return TEST_RESULT_SUCCESS;
140}
141
142/*
143 * Check that the counters are non-decreasing during
144 * a suspend/resume cycle.
145 */
146test_result_t test_amu_suspend_resume(void)
147{
148 uint64_t group0_ctrs[AMU_GROUP0_MAX_NR_COUNTERS];
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200149 int i;
150
151 if (!amu_supported())
152 return TEST_RESULT_SKIPPED;
153
154 /* If counters are not enabled, then skip the test */
John Tsichritzis68759a82019-05-12 15:10:27 +0100155 if (read_amcntenset0_el0() != AMU_GROUP0_COUNTERS_MASK)
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200156 return TEST_RESULT_SKIPPED;
157
158 /* Save counters values before suspend */
159 for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++)
160 group0_ctrs[i] = amu_group0_cnt_read(i);
161
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200162 /* Suspend/resume current core */
163 suspend_and_resume_this_cpu();
164
165 /*
166 * Check if counter values are >= than the stored values.
167 * If they are not, the AMU context save/restore in EL3 is buggy.
168 */
169 for (i = 0; i < AMU_GROUP0_NR_COUNTERS; i++) {
John Tsichritziscae91ca2019-05-12 16:06:09 +0100170 uint64_t value;
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200171
John Tsichritziscae91ca2019-05-12 16:06:09 +0100172 value = amu_group0_cnt_read(i);
173 if (value < group0_ctrs[i]) {
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200174 tftf_testcase_printf("Invalid counter value: before: %llx, after: %llx\n",
175 (unsigned long long)group0_ctrs[i],
John Tsichritziscae91ca2019-05-12 16:06:09 +0100176 (unsigned long long)value);
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200177 return TEST_RESULT_FAIL;
178 }
179 }
180
Sandrine Bailleux3cd87d72018-10-09 11:12:55 +0200181 return TEST_RESULT_SUCCESS;
182}