xref: /aosp_15_r20/trusty/kernel/app/memorylatencybench/main.c (revision 344aa361028b423587d4ef3fa52a23d194628137)
1*344aa361SAndroid Build Coastguard Worker /*
2*344aa361SAndroid Build Coastguard Worker  * Copyright (C) 2023 The Android Open Source Project
3*344aa361SAndroid Build Coastguard Worker  *
4*344aa361SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*344aa361SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*344aa361SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*344aa361SAndroid Build Coastguard Worker  *
8*344aa361SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*344aa361SAndroid Build Coastguard Worker  *
10*344aa361SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*344aa361SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*344aa361SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*344aa361SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*344aa361SAndroid Build Coastguard Worker  * limitations under the License.
15*344aa361SAndroid Build Coastguard Worker  */
16*344aa361SAndroid Build Coastguard Worker 
17*344aa361SAndroid Build Coastguard Worker #define TLOG_TAG "memlatency"
18*344aa361SAndroid Build Coastguard Worker 
19*344aa361SAndroid Build Coastguard Worker #include <inttypes.h>
20*344aa361SAndroid Build Coastguard Worker #include <stddef.h>
21*344aa361SAndroid Build Coastguard Worker #include <stdint.h>
22*344aa361SAndroid Build Coastguard Worker #include <stdlib.h>
23*344aa361SAndroid Build Coastguard Worker #include <string.h>
24*344aa361SAndroid Build Coastguard Worker 
25*344aa361SAndroid Build Coastguard Worker #include <arch/defines.h>
26*344aa361SAndroid Build Coastguard Worker #include <trusty_benchmark.h>
27*344aa361SAndroid Build Coastguard Worker #include <uapi/err.h>
28*344aa361SAndroid Build Coastguard Worker 
29*344aa361SAndroid Build Coastguard Worker #define BLOCK_SIZE_BYTES (CACHE_LINE * 4)
30*344aa361SAndroid Build Coastguard Worker #define STRUCT_NPAD (BLOCK_SIZE_BYTES) / sizeof(uintptr_t)
31*344aa361SAndroid Build Coastguard Worker #define MAX_WORKING_SET_SZ 16777216
32*344aa361SAndroid Build Coastguard Worker 
33*344aa361SAndroid Build Coastguard Worker static const uint64_t working_set_sizes[] = {
34*344aa361SAndroid Build Coastguard Worker         BLOCK_SIZE_BYTES,
35*344aa361SAndroid Build Coastguard Worker         512,
36*344aa361SAndroid Build Coastguard Worker         1024,
37*344aa361SAndroid Build Coastguard Worker         2048,
38*344aa361SAndroid Build Coastguard Worker         4096,
39*344aa361SAndroid Build Coastguard Worker         8192,
40*344aa361SAndroid Build Coastguard Worker         16384,
41*344aa361SAndroid Build Coastguard Worker         32768,
42*344aa361SAndroid Build Coastguard Worker         65536,
43*344aa361SAndroid Build Coastguard Worker         131072,
44*344aa361SAndroid Build Coastguard Worker         262144,
45*344aa361SAndroid Build Coastguard Worker         524288,
46*344aa361SAndroid Build Coastguard Worker         1048576,
47*344aa361SAndroid Build Coastguard Worker         2097152,
48*344aa361SAndroid Build Coastguard Worker         4194304,
49*344aa361SAndroid Build Coastguard Worker         8388608,
50*344aa361SAndroid Build Coastguard Worker         MAX_WORKING_SET_SZ,
51*344aa361SAndroid Build Coastguard Worker };
52*344aa361SAndroid Build Coastguard Worker 
53*344aa361SAndroid Build Coastguard Worker typedef union memlatency_state_t {
54*344aa361SAndroid Build Coastguard Worker     union memlatency_state_t* next;
55*344aa361SAndroid Build Coastguard Worker     uintptr_t pad[STRUCT_NPAD];
56*344aa361SAndroid Build Coastguard Worker } memlatency_state_t;
57*344aa361SAndroid Build Coastguard Worker 
58*344aa361SAndroid Build Coastguard Worker static memlatency_state_t* memlatency_state_start;
59*344aa361SAndroid Build Coastguard Worker 
60*344aa361SAndroid Build Coastguard Worker static size_t nb_blocks = MAX_WORKING_SET_SZ / sizeof(memlatency_state_t);
61*344aa361SAndroid Build Coastguard Worker 
get_param_name_cb_fixed(char * buf,size_t buf_size,size_t param_idx)62*344aa361SAndroid Build Coastguard Worker static void get_param_name_cb_fixed(char* buf,
63*344aa361SAndroid Build Coastguard Worker                                     size_t buf_size,
64*344aa361SAndroid Build Coastguard Worker                                     size_t param_idx) {
65*344aa361SAndroid Build Coastguard Worker     snprintf(buf, buf_size,
66*344aa361SAndroid Build Coastguard Worker              "%" PRIu64 " Bytes working size in blocks of %zu Bytes",
67*344aa361SAndroid Build Coastguard Worker              working_set_sizes[param_idx], sizeof(memlatency_state_t));
68*344aa361SAndroid Build Coastguard Worker }
69*344aa361SAndroid Build Coastguard Worker 
get_formatted_value_cb(char * buf,size_t buf_size,int64_t value,const char * metric_name)70*344aa361SAndroid Build Coastguard Worker static void get_formatted_value_cb(char* buf,
71*344aa361SAndroid Build Coastguard Worker                                    size_t buf_size,
72*344aa361SAndroid Build Coastguard Worker                                    int64_t value,
73*344aa361SAndroid Build Coastguard Worker                                    const char* metric_name) {
74*344aa361SAndroid Build Coastguard Worker     if (strcmp("time_micro_seconds", metric_name) == 0) {
75*344aa361SAndroid Build Coastguard Worker         int64_t mic_sec = value / 1000;
76*344aa361SAndroid Build Coastguard Worker         int64_t n_sec = value % 1000;
77*344aa361SAndroid Build Coastguard Worker 
78*344aa361SAndroid Build Coastguard Worker         snprintf(buf, buf_size, "%" PRId64 ".%03" PRId64 "", mic_sec, n_sec);
79*344aa361SAndroid Build Coastguard Worker     } else {
80*344aa361SAndroid Build Coastguard Worker         snprintf(buf, buf_size, "%" PRId64, value);
81*344aa361SAndroid Build Coastguard Worker     }
82*344aa361SAndroid Build Coastguard Worker }
83*344aa361SAndroid Build Coastguard Worker 
84*344aa361SAndroid Build Coastguard Worker static uint64_t mem_lat_pmu_evt_arr[] = {PMU_EV_CPU_CYCLES,
85*344aa361SAndroid Build Coastguard Worker                                          PMU_EV_INST_RETIRED};
86*344aa361SAndroid Build Coastguard Worker 
BENCH_SETUP(memlatency)87*344aa361SAndroid Build Coastguard Worker BENCH_SETUP(memlatency) {
88*344aa361SAndroid Build Coastguard Worker     BENCH_INIT_PMU(mem_lat_pmu_evt_arr);
89*344aa361SAndroid Build Coastguard Worker     trusty_bench_get_param_name_cb = &get_param_name_cb_fixed;
90*344aa361SAndroid Build Coastguard Worker     trusty_bench_get_formatted_value_cb = &get_formatted_value_cb;
91*344aa361SAndroid Build Coastguard Worker     memlatency_state_start =
92*344aa361SAndroid Build Coastguard Worker             memalign(CACHE_LINE, nb_blocks * sizeof(memlatency_state_t));
93*344aa361SAndroid Build Coastguard Worker 
94*344aa361SAndroid Build Coastguard Worker     if (memlatency_state_start == NULL) {
95*344aa361SAndroid Build Coastguard Worker         TLOGE("Failed to Allocate memory for memlatency_state!");
96*344aa361SAndroid Build Coastguard Worker         return ERR_NO_MEMORY;
97*344aa361SAndroid Build Coastguard Worker     }
98*344aa361SAndroid Build Coastguard Worker 
99*344aa361SAndroid Build Coastguard Worker     memset((uint8_t*)memlatency_state_start, 0,
100*344aa361SAndroid Build Coastguard Worker            nb_blocks * sizeof(memlatency_state_t));
101*344aa361SAndroid Build Coastguard Worker 
102*344aa361SAndroid Build Coastguard Worker     for (size_t idx = 0; idx < nb_blocks - 1; ++idx) {
103*344aa361SAndroid Build Coastguard Worker         memlatency_state_start[idx].next = &memlatency_state_start[idx + 1];
104*344aa361SAndroid Build Coastguard Worker     }
105*344aa361SAndroid Build Coastguard Worker 
106*344aa361SAndroid Build Coastguard Worker     static_assert(sizeof(memlatency_state_t) == BLOCK_SIZE_BYTES);
107*344aa361SAndroid Build Coastguard Worker 
108*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
109*344aa361SAndroid Build Coastguard Worker }
110*344aa361SAndroid Build Coastguard Worker 
BENCH_TEARDOWN(memlatency)111*344aa361SAndroid Build Coastguard Worker BENCH_TEARDOWN(memlatency) {
112*344aa361SAndroid Build Coastguard Worker     free(memlatency_state_start);
113*344aa361SAndroid Build Coastguard Worker     memlatency_state_start = NULL;
114*344aa361SAndroid Build Coastguard Worker }
115*344aa361SAndroid Build Coastguard Worker 
116*344aa361SAndroid Build Coastguard Worker BENCH(memlatency, latency_read, 20, working_set_sizes) {
117*344aa361SAndroid Build Coastguard Worker     uint64_t sz = working_set_sizes[bench_get_param_idx()];
118*344aa361SAndroid Build Coastguard Worker     uint64_t nb_blocks = sz / BLOCK_SIZE_BYTES;
119*344aa361SAndroid Build Coastguard Worker     uint64_t loops = 10 * (MAX_WORKING_SET_SZ / sz);
120*344aa361SAndroid Build Coastguard Worker 
121*344aa361SAndroid Build Coastguard Worker     ASSERT_GT(nb_blocks, 0);
122*344aa361SAndroid Build Coastguard Worker 
123*344aa361SAndroid Build Coastguard Worker     while (loops > 0) {
124*344aa361SAndroid Build Coastguard Worker         --loops;
125*344aa361SAndroid Build Coastguard Worker         volatile union memlatency_state_t* block = memlatency_state_start;
126*344aa361SAndroid Build Coastguard Worker 
127*344aa361SAndroid Build Coastguard Worker         for (size_t idx = 0; idx < nb_blocks; idx++) {
128*344aa361SAndroid Build Coastguard Worker             /* To make sure we are not overwriting next block Address */
129*344aa361SAndroid Build Coastguard Worker             static_assert(sizeof(uintptr_t) == __SIZEOF_POINTER__);
130*344aa361SAndroid Build Coastguard Worker             block = block->next;
131*344aa361SAndroid Build Coastguard Worker         }
132*344aa361SAndroid Build Coastguard Worker     }
133*344aa361SAndroid Build Coastguard Worker 
134*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
135*344aa361SAndroid Build Coastguard Worker test_abort:
136*344aa361SAndroid Build Coastguard Worker     return ERR_GENERIC;
137*344aa361SAndroid Build Coastguard Worker }
138*344aa361SAndroid Build Coastguard Worker 
139*344aa361SAndroid Build Coastguard Worker BENCH(memlatency, latency_write, 20, working_set_sizes) {
140*344aa361SAndroid Build Coastguard Worker     uint64_t sz = working_set_sizes[bench_get_param_idx()];
141*344aa361SAndroid Build Coastguard Worker     uint64_t nb_blocks = sz / BLOCK_SIZE_BYTES;
142*344aa361SAndroid Build Coastguard Worker     uint64_t loops = 10 * (MAX_WORKING_SET_SZ / sz);
143*344aa361SAndroid Build Coastguard Worker 
144*344aa361SAndroid Build Coastguard Worker     ASSERT_GT(nb_blocks, 0);
145*344aa361SAndroid Build Coastguard Worker 
146*344aa361SAndroid Build Coastguard Worker     while (loops > 0) {
147*344aa361SAndroid Build Coastguard Worker         --loops;
148*344aa361SAndroid Build Coastguard Worker         union memlatency_state_t* block = memlatency_state_start;
149*344aa361SAndroid Build Coastguard Worker 
150*344aa361SAndroid Build Coastguard Worker         for (size_t idx = 0; idx < nb_blocks; idx++) {
151*344aa361SAndroid Build Coastguard Worker             /* To make sure we are not overwriting next block Address */
152*344aa361SAndroid Build Coastguard Worker             static_assert(sizeof(uintptr_t) == __SIZEOF_POINTER__);
153*344aa361SAndroid Build Coastguard Worker             (block + idx)->pad[1] = idx + sz;
154*344aa361SAndroid Build Coastguard Worker         }
155*344aa361SAndroid Build Coastguard Worker     }
156*344aa361SAndroid Build Coastguard Worker 
157*344aa361SAndroid Build Coastguard Worker     return NO_ERROR;
158*344aa361SAndroid Build Coastguard Worker test_abort:
159*344aa361SAndroid Build Coastguard Worker     return ERR_GENERIC;
160*344aa361SAndroid Build Coastguard Worker }
161*344aa361SAndroid Build Coastguard Worker 
BENCH_RESULT(memlatency,latency_read,time_micro_seconds)162*344aa361SAndroid Build Coastguard Worker BENCH_RESULT(memlatency, latency_read, time_micro_seconds) {
163*344aa361SAndroid Build Coastguard Worker     return bench_get_duration_ns();
164*344aa361SAndroid Build Coastguard Worker }
165*344aa361SAndroid Build Coastguard Worker 
BENCH_RESULT(memlatency,latency_write,time_micro_seconds)166*344aa361SAndroid Build Coastguard Worker BENCH_RESULT(memlatency, latency_write, time_micro_seconds) {
167*344aa361SAndroid Build Coastguard Worker     return bench_get_duration_ns();
168*344aa361SAndroid Build Coastguard Worker }
169*344aa361SAndroid Build Coastguard Worker 
BENCH_RESULT(memlatency,latency_read,cycle_counter_0)170*344aa361SAndroid Build Coastguard Worker BENCH_RESULT(memlatency, latency_read, cycle_counter_0) {
171*344aa361SAndroid Build Coastguard Worker     return bench_get_pmu_cnt(0);
172*344aa361SAndroid Build Coastguard Worker }
173*344aa361SAndroid Build Coastguard Worker 
BENCH_RESULT(memlatency,latency_read,cycle_counter)174*344aa361SAndroid Build Coastguard Worker BENCH_RESULT(memlatency, latency_read, cycle_counter) {
175*344aa361SAndroid Build Coastguard Worker     return bench_get_pmu_cnt(1);
176*344aa361SAndroid Build Coastguard Worker }
177*344aa361SAndroid Build Coastguard Worker 
BENCH_RESULT(memlatency,latency_read,inst_retired)178*344aa361SAndroid Build Coastguard Worker BENCH_RESULT(memlatency, latency_read, inst_retired) {
179*344aa361SAndroid Build Coastguard Worker     return bench_get_pmu_cnt(2);
180*344aa361SAndroid Build Coastguard Worker }
181*344aa361SAndroid Build Coastguard Worker 
182*344aa361SAndroid Build Coastguard Worker PORT_TEST(memlatency, "com.android.kernel.memorylatency.bench");
183