1 /*
2  * Copyright (c) 2019 LK Trusty Authors. All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 
24 #include <kernel/timer.h>
25 #include <lib/unittest/unittest.h>
26 #include <platform.h>
27 #include <stdatomic.h>
28 
29 #define US2NS(us) ((us) * 1000LL)
30 #define MS2NS(ms) (US2NS(ms) * 1000LL)
31 #define S2NS(s) (MS2NS(s) * 1000LL)
32 
33 /* Expect better than 1us timer resolution. */
34 #if GEM5
35 // In gem5 simulation CNTPCT register is updated with frequency less than
36 // 1MHz, so adjust target period for this test
37 #define TIMER_TEST_MAX_CLOCK_PERIOD (1200)
38 #elif defined(APP_TIMERTEST_MAX_CLOCK_PERIOD)
39 #define TIMER_TEST_MAX_CLOCK_PERIOD (APP_TIMERTEST_MAX_CLOCK_PERIOD)
40 #else
41 #define TIMER_TEST_MAX_CLOCK_PERIOD (900)
42 #endif
43 
44 /*
45  * Expect much better than 1ms timer interrupt latency, but qemu currently has
46  * more than 100us latency in the best case, and Linux adds several milliseconds
47  * to this in the worst case.
48  */
49 #define TIMER_TEST_MAX_TIMER_LATENCY (MS2NS(10))
50 
51 /* Periodic timers don't currently avoid drifting when the interrupt is late */
52 #define TIMER_TEST_MAX_TIMER_DRIFT TIMER_TEST_MAX_TIMER_LATENCY
53 
54 #define TIMER_TEST_RETRY_COUNT (10)
55 
TimerTestGetTimeNs(void)56 static int64_t TimerTestGetTimeNs(void) {
57     return current_time_ns();
58 }
59 
TimerTestBusyWait(int64_t delay)60 static void TimerTestBusyWait(int64_t delay) {
61     int64_t end = TimerTestGetTimeNs() + delay;
62     while (TimerTestGetTimeNs() < end) {
63     }
64 }
65 
66 struct TimerTestTimer {
67     struct timer timer;
68     int64_t delta;
69     int64_t before_start_time;
70     int64_t after_start_time;
71     size_t target_trigger_count;
72     atomic_size_t trigger_count;
73     int64_t trigger_time_passed;
74     int64_t handler_run_time;
75     void *arg_passed;
76 };
77 
78 #define TIMER_TEST_TIMER_INITIAL_VALUE(t) { \
79         TIMER_INITIAL_VALUE(&t->timer), 0, 0, 0, 0, 0, 0, 0, NULL \
80     }
81 
ToTimerTestTimer(struct timer * timer)82 static struct TimerTestTimer *ToTimerTestTimer(struct timer *timer) {
83     return containerof(timer, struct TimerTestTimer, timer);
84 }
85 
86 /**
87  * TimerTestTimerCallback - Timer callback function.
88  * @timer:  Timer object.
89  * @now:    Current time passed from lk timer code.
90  * @arg:    Argument passed to timer_set*.
91  *
92  * Common timer callback function used by tests to record how many times it was
93  * called, when it was last called and what arguments were passed. Stops
94  * periodic timer after a specified trigger count.
95  *
96  * Return: INT_NO_RESCHEDULE to tell the caller that the scheduler does not need
97  *         to run.
98  */
TimerTestTimerCallback(struct timer * timer,lk_time_ns_t now,void * arg)99 static enum handler_return TimerTestTimerCallback(struct timer *timer,
100                                                   lk_time_ns_t now,
101                                                   void *arg) {
102     struct TimerTestTimer *t = ToTimerTestTimer(timer);
103     size_t trigger_count;
104 
105     t->trigger_time_passed = now;
106     t->handler_run_time = TimerTestGetTimeNs();
107     t->arg_passed = arg;
108     trigger_count = atomic_fetch_add_explicit(&t->trigger_count, 1,
109                                               memory_order_release) + 1;
110     if (t->timer.periodic_time &&
111         trigger_count == t->target_trigger_count) {
112         timer_cancel(&t->timer);
113     }
114     return INT_NO_RESCHEDULE;
115 }
116 
117 /**
118  * TimerTestTimerStart - Start test timer.
119  * @t:      Test timer object.
120  * @delta:  Delay in nanoseconds until timer callback should be called and
121  *          interval between timer callback calls if @count is greater than one.
122  * @count:  Number of times to call the timer callback.
123  */
TimerTestTimerStart(struct TimerTestTimer * t,int64_t delta,size_t count)124 static void TimerTestTimerStart(struct TimerTestTimer *t, int64_t delta,
125                                 size_t count) {
126     lk_time_ns_t lk_time = delta;
127     t->delta = delta;
128     t->target_trigger_count = count;
129     atomic_store(&t->trigger_count, 0);
130     t->before_start_time = TimerTestGetTimeNs();
131     if (count > 1) {
132         timer_set_periodic_ns(&t->timer, lk_time, TimerTestTimerCallback, t);
133     } else {
134         timer_set_oneshot_ns(&t->timer, lk_time, TimerTestTimerCallback, t);
135     }
136     t->after_start_time = TimerTestGetTimeNs();
137 }
138 
139 /**
140  * TimerTestTimerCheck - Check that timer callback was called
141  * @t:      Test timer object.
142  * @retry:  If non-zero, return early if timer callback ran late.
143  *
144  * Return: @retry if timer callback ran late and test should run again, 0
145  *         otherwise.
146  */
TimerTestTimerCheck(struct TimerTestTimer * t,size_t retry)147 static size_t TimerTestTimerCheck(struct TimerTestTimer *t, size_t retry) {
148     size_t trigger_count;
149     int64_t delta = t->delta * t->target_trigger_count;
150     int64_t min_delta = delta;
151     int64_t max_delta = delta + TIMER_TEST_MAX_TIMER_LATENCY +
152                         TIMER_TEST_MAX_TIMER_DRIFT *
153                         (t->target_trigger_count - 1);
154 
155     trigger_count = atomic_load_explicit(&t->trigger_count,
156                                          memory_order_acquire);
157 
158     EXPECT_EQ(trigger_count, t->target_trigger_count);
159     timer_cancel_sync(&t->timer);
160     if (trigger_count != t->target_trigger_count) {
161         return 0;
162     }
163 
164     EXPECT_EQ(t->arg_passed, t);
165 
166     if (retry && MAX(t->trigger_time_passed, t->handler_run_time) -
167                  t->after_start_time >= max_delta) {
168         unittest_printf("    %lld/%lld > %lld, retry\n",
169                         t->trigger_time_passed - t->after_start_time,
170                         t->handler_run_time - t->after_start_time, max_delta);
171         return retry;
172     }
173 
174     EXPECT_GE(t->trigger_time_passed - t->before_start_time, min_delta);
175     EXPECT_LT(t->trigger_time_passed - t->after_start_time, max_delta);
176     EXPECT_GE(t->handler_run_time - t->before_start_time, min_delta);
177     EXPECT_LT(t->handler_run_time - t->after_start_time, max_delta);
178 
179     return 0;
180 }
181 
182 /**
183  * TimerTestTimerPoll - Busy wait for timer callback to run.
184  * @t:          Test timer object.
185  * @timeout:    Timeout in nanoseconds to abort busy-wait.
186  *
187  * Return: %true if timer callback ran the expected number of times, %false
188  *         otherwise.
189  */
TimerTestTimerPoll(struct TimerTestTimer * t,int64_t timeout)190 static bool TimerTestTimerPoll(struct TimerTestTimer *t, int64_t timeout) {
191     size_t trigger_count;
192     int64_t end_time = TimerTestGetTimeNs() + timeout;
193 
194     do {
195         trigger_count = atomic_load_explicit(&t->trigger_count,
196                                              memory_order_acquire);
197     } while (trigger_count < t->target_trigger_count &&
198              TimerTestGetTimeNs() < end_time);
199 
200     return trigger_count == t->target_trigger_count;
201 }
202 
203 /* Test high resolution api to read timer */
TEST(TimerTest,GetTime)204 TEST(TimerTest, GetTime) {
205     int64_t t1;
206     int64_t t2;
207     size_t i;
208     const int timeout = 1000;
209     const int64_t max_delta = TIMER_TEST_MAX_CLOCK_PERIOD;
210 
211     t2 = TimerTestGetTimeNs();
212     for (i = 0; i < timeout; i++) {
213         t1 = t2;
214         t2 =  TimerTestGetTimeNs();
215         if (t2 != t1 && t2 - t1 <= max_delta) {
216             break;
217         }
218     }
219     EXPECT_GT(t2 - t1, 0);
220     EXPECT_LE(t2 - t1, max_delta);
221 }
222 
223 /* Test one shot timer api */
TEST(TimerTest,TimerSetOneShot)224 TEST(TimerTest, TimerSetOneShot) {
225     struct TimerTestTimer t = TIMER_TEST_TIMER_INITIAL_VALUE(&t);
226     int retry = TIMER_TEST_RETRY_COUNT;
227     do {
228         TimerTestTimerStart(&t, MS2NS(1), 1);
229         TimerTestTimerPoll(&t, S2NS(10));
230         retry = TimerTestTimerCheck(&t, retry - 1);
231     } while(retry);
232 }
233 
234 /* Test periodic timer api */
TEST(TimerTest,TimerSetPeriodic)235 TEST(TimerTest, TimerSetPeriodic) {
236     struct TimerTestTimer t = TIMER_TEST_TIMER_INITIAL_VALUE(&timer);
237     int retry = TIMER_TEST_RETRY_COUNT;
238     do {
239         TimerTestTimerStart(&t, MS2NS(1), 100);
240         TimerTestTimerPoll(&t, S2NS(10));
241         retry = TimerTestTimerCheck(&t, retry - 1);
242     } while(retry);
243 }
244 
245 /* Test multiple timers (which could cause early wake up in old timer code) */
TEST(TimerTest,TimerSetOneShotMultipleEvenlySpaced)246 TEST(TimerTest, TimerSetOneShotMultipleEvenlySpaced) {
247     size_t i;
248     static struct TimerTestTimer tb[] = {
249         TIMER_TEST_TIMER_INITIAL_VALUE(&tb[0]),
250         TIMER_TEST_TIMER_INITIAL_VALUE(&tb[1]),
251         TIMER_TEST_TIMER_INITIAL_VALUE(&tb[2]),
252         TIMER_TEST_TIMER_INITIAL_VALUE(&tb[3]),
253         TIMER_TEST_TIMER_INITIAL_VALUE(&tb[4]),
254         TIMER_TEST_TIMER_INITIAL_VALUE(&tb[5]),
255         TIMER_TEST_TIMER_INITIAL_VALUE(&tb[6]),
256         TIMER_TEST_TIMER_INITIAL_VALUE(&tb[7]),
257         TIMER_TEST_TIMER_INITIAL_VALUE(&tb[8]),
258         TIMER_TEST_TIMER_INITIAL_VALUE(&tb[9]),
259     };
260     static struct TimerTestTimer ts[] = {
261         TIMER_TEST_TIMER_INITIAL_VALUE(&ts[0]),
262         TIMER_TEST_TIMER_INITIAL_VALUE(&ts[1]),
263         TIMER_TEST_TIMER_INITIAL_VALUE(&ts[2]),
264         TIMER_TEST_TIMER_INITIAL_VALUE(&ts[3]),
265         TIMER_TEST_TIMER_INITIAL_VALUE(&ts[4]),
266         TIMER_TEST_TIMER_INITIAL_VALUE(&ts[5]),
267         TIMER_TEST_TIMER_INITIAL_VALUE(&ts[6]),
268         TIMER_TEST_TIMER_INITIAL_VALUE(&ts[7]),
269         TIMER_TEST_TIMER_INITIAL_VALUE(&ts[8]),
270         TIMER_TEST_TIMER_INITIAL_VALUE(&ts[9]),
271     };
272     int retry = TIMER_TEST_RETRY_COUNT;
273     int next_retry;
274     do {
275         for (i = 0; i < countof(tb); i++) {
276             TimerTestTimerStart(&tb[i], MS2NS(1), 1);
277         }
278         for (i = 0; i < countof(ts); i++) {
279             TimerTestTimerStart(&ts[i], MS2NS(1), 1);
280             TimerTestBusyWait(MS2NS(1) / countof(ts));
281             timer_cancel_sync(&tb[i].timer);
282         }
283         TimerTestTimerPoll(&ts[countof(ts) - 1], S2NS(10));
284         for (i = 0; i < countof(ts); i++) {
285             /* thread may migrate to another cpu */
286             TimerTestTimerPoll(&ts[i], S2NS(1));
287         }
288         next_retry = retry - 1;
289         retry = 0;
290         for (i = 0; i < countof(ts); i++) {
291             int tmp_retry = TimerTestTimerCheck(&ts[i], next_retry);
292             if (tmp_retry) {
293                 retry = tmp_retry;
294             }
295         }
296     } while(retry);
297 }
298 
299 /*
300  * Test timer_cancel api. Call after a delay from alternating CPUs to try to
301  * cancel it while the timer callback is running.
302  */
TEST(TimerTest,TimerCancel)303 TEST(TimerTest, TimerCancel) {
304     struct TimerTestTimer t = TIMER_TEST_TIMER_INITIAL_VALUE(&t);
305     struct wait_queue wq = WAIT_QUEUE_INITIAL_VALUE(wq);
306     bool triggered;
307     int64_t wait_time = MS2NS(2);
308     int saved_pinned_cpu = thread_pinned_cpu(get_current_thread());
309     EXPECT_EQ(saved_pinned_cpu, -1);
310     for (int i = 0; i < 1000; i++) {
311         TimerTestTimerStart(&t, MS2NS(2), 1);
312         thread_set_pinned_cpu(get_current_thread(),
313                               (arch_curr_cpu_num() + 1) % 2);
314         THREAD_LOCK(state);
315         wait_queue_block(&wq, 1);
316         THREAD_UNLOCK(state);
317         triggered = TimerTestTimerPoll(&t, wait_time);
318         if (!triggered) {
319             wait_time += US2NS(10);
320         } else {
321             wait_time -= US2NS(10);
322         }
323         timer_cancel_sync(&t.timer);
324     }
325     thread_set_pinned_cpu(get_current_thread(), saved_pinned_cpu);
326 }
327 
328 PORT_TEST(TimerTest, "com.android.kernel.timertest");
329