1 /*
2 * \file mem_acc_test.cpp
3 * \brief OpenCSD : Component tests for memory accessor and caching
4 *
5 * \copyright Copyright (c) 2023, ARM Limited. All Rights Reserved.
6 */
7
8
9 /*
10 * Redistribution and use in source and binary forms, with or without modification,
11 * are permitted provided that the following conditions are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright notice,
17 * this list of conditions and the following disclaimer in the documentation
18 * and/or other materials provided with the distribution.
19 *
20 * 3. Neither the name of the copyright holder nor the names of its contributors
21 * may be used to endorse or promote products derived from this software without
22 * specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 */
35
36 /*
37 * Test program to validate the memory accessor and caching.
38 *
39 * Checks for memory spaces, overlapping VA, cache sizes
40 */
41
42 #include <cstdio>
43 #include <string>
44 #include <iostream>
45 #include <sstream>
46 #include <cstring>
47
48 #include "opencsd.h"
49
50 // logging
51 static ocsdMsgLogger logger;
52 static ocsdDefaultErrorLogger err_log;
53 static ocsd_hndl_err_log_t err_log_handle;
54 static int logOpts = ocsdMsgLogger::OUT_STDOUT | ocsdMsgLogger::OUT_FILE;
55 static std::string logfileName = "mem_acc_test.ppl";
56
57 // test pass fail counts
58 static int tests_passed = 0;
59 static int tests_failed = 0;
60
61 // number of blocks per memory area
62 #define NUM_BLOCKS 2
63 // number of 32 but words in each block
64 #define BLOCK_NUM_WORDS 8192
65 // size of block in bytes
66 #define BLOCK_SIZE_BYTES (4 * BLOCK_NUM_WORDS)
67
68 // some memory areas to use for testing
69 static uint32_t el01_ns_blocks[NUM_BLOCKS][BLOCK_NUM_WORDS];
70 static uint32_t el2_ns_blocks[NUM_BLOCKS][BLOCK_NUM_WORDS];
71 static uint32_t el01_s_blocks[NUM_BLOCKS][BLOCK_NUM_WORDS];
72 static uint32_t el2_s_blocks[NUM_BLOCKS][BLOCK_NUM_WORDS];
73 static uint32_t el3_blocks[NUM_BLOCKS][BLOCK_NUM_WORDS];
74 static uint32_t el01_r_blocks[NUM_BLOCKS][BLOCK_NUM_WORDS];
75 static uint32_t el2_r_blocks[NUM_BLOCKS][BLOCK_NUM_WORDS];
76 static uint32_t el3_root_blocks[NUM_BLOCKS][BLOCK_NUM_WORDS];
77
78 #define BLOCK_VAL(mem_space, block_num, index) (uint32_t)(((uint32_t)mem_space << 24) | ((uint32_t)block_num << 16) | (uint32_t)index)
79
80 // memory access mapper - used for tests
81 static TrcMemAccMapGlobalSpace mapper;
82
83
84
populate_block(const ocsd_mem_space_acc_t mem_space,uint32_t block_array[NUM_BLOCKS][BLOCK_NUM_WORDS])85 void populate_block(const ocsd_mem_space_acc_t mem_space, uint32_t block_array[NUM_BLOCKS][BLOCK_NUM_WORDS])
86 {
87 for (int i = 0; i < NUM_BLOCKS; i++) {
88 for (int j = 0; j < BLOCK_NUM_WORDS; j++)
89 block_array[i][j] = BLOCK_VAL(mem_space, i, j);
90 }
91 }
92
populate_all_blocks()93 void populate_all_blocks()
94 {
95 populate_block(OCSD_MEM_SPACE_EL1N, el01_ns_blocks);
96 populate_block(OCSD_MEM_SPACE_EL2, el2_ns_blocks);
97 populate_block(OCSD_MEM_SPACE_EL1S, el01_s_blocks);
98 populate_block(OCSD_MEM_SPACE_EL2S, el2_s_blocks);
99 populate_block(OCSD_MEM_SPACE_EL3, el3_blocks);
100 populate_block(OCSD_MEM_SPACE_EL1R, el01_r_blocks);
101 populate_block(OCSD_MEM_SPACE_EL2R, el2_r_blocks);
102 populate_block(OCSD_MEM_SPACE_ROOT, el3_root_blocks);
103 }
104
process_cmd_line_logger_opts(int argc,char * argv[])105 bool process_cmd_line_logger_opts(int argc, char* argv[])
106 {
107 bool goodLoggerOpts = true;
108 bool bChangingOptFlags = false;
109 int newlogOpts = ocsdMsgLogger::OUT_NONE;
110 std::string opt;
111 if (argc > 1)
112 {
113 int options_to_process = argc - 1;
114 int optIdx = 1;
115 while (options_to_process > 0)
116 {
117 opt = argv[optIdx];
118 if (opt == "-logstdout")
119 {
120 newlogOpts |= ocsdMsgLogger::OUT_STDOUT;
121 bChangingOptFlags = true;
122 }
123 else if (opt == "-logstderr")
124 {
125 newlogOpts |= ocsdMsgLogger::OUT_STDERR;
126 bChangingOptFlags = true;
127 }
128 else if (opt == "-logfile")
129 {
130 newlogOpts |= ocsdMsgLogger::OUT_FILE;
131 bChangingOptFlags = true;
132 }
133 else if (opt == "-logfilename")
134 {
135 options_to_process--;
136 optIdx++;
137 if (options_to_process)
138 {
139 logfileName = argv[optIdx];
140 newlogOpts |= ocsdMsgLogger::OUT_FILE;
141 bChangingOptFlags = true;
142 }
143 else
144 {
145 goodLoggerOpts = false;
146 }
147 }
148 options_to_process--;
149 optIdx++;
150 }
151 }
152 if (bChangingOptFlags)
153 logOpts = newlogOpts;
154 return goodLoggerOpts;
155 }
156
log_error(const ocsdError & err)157 void log_error(const ocsdError& err)
158 {
159 err_log.LogError(err_log_handle, &err);
160 }
161
log_test_start(const char * testname)162 void log_test_start(const char* testname)
163 {
164 std::ostringstream oss;
165 oss << "*** Test " << testname << " Starting.\n";
166 logger.LogMsg(oss.str());
167 }
168
log_test_end(const char * testname,const int pass,const int fail)169 void log_test_end(const char* testname, const int pass, const int fail)
170 {
171 std::ostringstream oss;
172 oss << "*** Test " << testname << " complete. (Pass: " << pass << "; Fail:" << fail << ")\n";
173 logger.LogMsg(oss.str());
174 }
175
test_overlap_regions()176 void test_overlap_regions()
177 {
178 // test adding regions that overlap
179 // overlap in difference memory spaces is ok, otherwise fail
180 TrcMemAccBufPtr Acc1, Acc2, Acc3, Acc4;
181 ocsd_err_t err;
182 std::ostringstream oss;
183 int passed = 0, failed = 0;
184
185 log_test_start(__FUNCTION__);
186
187 // add single accessor
188 Acc1.initAccessor(0x0000, (const uint8_t*)&el01_ns_blocks[0], BLOCK_SIZE_BYTES);
189 Acc1.setMemSpace(OCSD_MEM_SPACE_EL1N);
190 err = mapper.AddAccessor(&Acc1, 0);
191 if (err != OCSD_OK) {
192 log_error(ocsdError(OCSD_ERR_SEV_ERROR, err, "Failed to set memory accessor"));
193 failed++;
194 }
195 else
196 passed++;
197
198 // overlapping region - same memory space.
199 Acc2.initAccessor(0x1000, (const uint8_t*)&el01_ns_blocks[1], BLOCK_SIZE_BYTES);
200 Acc2.setMemSpace(OCSD_MEM_SPACE_EL1N);
201 err = mapper.AddAccessor(&Acc2, 0);
202 if (err != OCSD_ERR_MEM_ACC_OVERLAP) {
203 oss.str("");
204 oss << "Error: expected OCSD_ERR_MEM_ACC_OVERLAP error for overlapping accessor range.\n";
205 logger.LogMsg(oss.str());
206 failed++;
207 }
208 else
209 passed++;
210
211 // non overlapping region - same memory space.
212 Acc2.setRange(0x8000, 0x8000 + BLOCK_SIZE_BYTES - 1);
213 err = mapper.AddAccessor(&Acc2, 0);
214 if (err != OCSD_OK) {
215 log_error(ocsdError(OCSD_ERR_SEV_ERROR, err, "Failed to set non overlapping memory accessor"));
216 failed++;
217 }
218 else
219 passed++;
220
221 // overlapping region - different memory space
222 Acc3.initAccessor(0x0000, (const uint8_t*)&el01_s_blocks[0], BLOCK_SIZE_BYTES);
223 Acc3.setMemSpace(OCSD_MEM_SPACE_EL1S);
224 err = mapper.AddAccessor(&Acc3, 0);
225 if (err != OCSD_OK) {
226 log_error(ocsdError(OCSD_ERR_SEV_ERROR, err, "Failed to set overlapping memory accessor in other memory space"));
227 failed++;
228 }
229 else
230 passed++;
231
232 // overlapping region - more general memory space.
233 Acc4.initAccessor(0x0000, (const uint8_t*)&el2_s_blocks[0], BLOCK_SIZE_BYTES);
234 Acc4.setMemSpace(OCSD_MEM_SPACE_S);
235 err = mapper.AddAccessor(&Acc4, 0);
236 if (err != OCSD_ERR_MEM_ACC_OVERLAP) {
237 oss.str("");
238 oss << "Error: expected OCSD_ERR_MEM_ACC_OVERLAP error for overlapping general _S accessor range.\n";
239 logger.LogMsg(oss.str());
240 failed++;
241 }
242 else
243 passed++;
244
245 // clean up mapper
246 mapper.RemoveAllAccessors();
247 tests_passed += passed;
248 tests_failed += failed;
249
250 log_test_end(__FUNCTION__, passed, failed);
251 }
252 /************************************************************************
253 * Test trcID specific memory regions - using callback function.
254 * Emulates clinets such as perf where memory regions change over the
255 * trace run as tasks switched in and out. Tests caching mechanisms in
256 * mapper.
257 */
258 typedef struct test_range {
259 ocsd_vaddr_t s_address;
260 uint32_t size;
261 const uint8_t* buffer;
262 ocsd_mem_space_acc_t mem_space;
263 uint8_t trcID;
264 } test_range_t;
265
266 typedef struct test_range_array {
267 int num_ranges;
268 test_range_t* ranges;
269 } test_range_array_t;
270
271 #define IN_MEM_SPACE(m1, m2) (bool)(((uint32_t)m1)&((uint32_t)m2))
272
273 static int AccCallbackCount = 0;
274
TestMemAccCB(const void * p_context,const ocsd_vaddr_t address,const ocsd_mem_space_acc_t mem_space,const uint8_t trcID,const uint32_t reqBytes,uint8_t * byteBuffer)275 uint32_t TestMemAccCB(const void* p_context, const ocsd_vaddr_t address, const ocsd_mem_space_acc_t mem_space, const uint8_t trcID, const uint32_t reqBytes, uint8_t* byteBuffer)
276 {
277 test_range_array_t* ranges = (test_range_array_t*)p_context;
278 uint32_t bytes_read = 0;
279
280 for (int i = 0; i < ranges->num_ranges; i++)
281 {
282 if ( IN_MEM_SPACE(mem_space, ranges->ranges[i].mem_space) &&
283 (trcID == ranges->ranges[i].trcID)
284 )
285 {
286 if ( (address >= ranges->ranges[i].s_address) &&
287 (address < (ranges->ranges[i].s_address + ranges->ranges[i].size))
288 )
289 {
290 // in range - get offset into buffer
291 uint32_t offset = address - ranges->ranges[i].s_address;
292
293 // copy all bytes if enough left in range - otherwise what if left
294 if (ranges->ranges[i].size - offset >= reqBytes)
295 bytes_read = reqBytes;
296 else
297 bytes_read = ranges->ranges[i].size - offset;
298
299 memcpy(byteBuffer, &(ranges->ranges[i].buffer[offset]), bytes_read);
300 break;
301 }
302 }
303 }
304 AccCallbackCount++;
305 return bytes_read;
306 }
307
set_test_range(test_range_t & range,ocsd_vaddr_t s_address,uint32_t size,const uint8_t * buffer,ocsd_mem_space_acc_t mem_space,uint8_t trcID)308 void set_test_range(test_range_t& range, ocsd_vaddr_t s_address, uint32_t size,
309 const uint8_t* buffer, ocsd_mem_space_acc_t mem_space, uint8_t trcID)
310 {
311 range.s_address = s_address;
312 range.size = size;
313 range.buffer = buffer;
314 range.mem_space = mem_space;
315 range.trcID = trcID;
316 }
317
318 // read value through mapper and direct from range - check value and callback happened
319 // allows testing of expected caching and callback events
read_and_check_from_range(const int test_idx,const int range,test_range_array_t & ranges,const ocsd_vaddr_t byte_offset,bool callback)320 bool read_and_check_from_range(const int test_idx, const int range, test_range_array_t& ranges, const ocsd_vaddr_t byte_offset, bool callback)
321 {
322 uint32_t read_val, num_bytes_read, expected_val;
323 uint8_t* p_local_buff = (uint8_t*)&read_val;
324 int PrevAccCallbackCount = AccCallbackCount;
325 ocsd_err_t err;
326 ocsd_vaddr_t read_address;
327 bool pass = true, mem_callback_occurred = false;
328 std::ostringstream oss;
329 std::string memSpaceStr;
330 ocsd_mem_space_acc_t mem_space;
331 uint8_t traceID;
332
333
334 mem_space = ranges.ranges[range].mem_space;
335 read_address = ranges.ranges[range].s_address + byte_offset; // set address value
336 num_bytes_read = 4; // request 4 bytes
337 expected_val = *((uint32_t *)(&(ranges.ranges[range].buffer[byte_offset])));
338 traceID = ranges.ranges[range].trcID;
339 TrcMemAccessorBase::getMemAccSpaceString(memSpaceStr, mem_space);
340
341 oss << "Read Test(" << test_idx << "): Address 0x" << std::hex << std::setw(8) << std::setfill('0') << read_address << "; ";
342 oss << memSpaceStr << "; Traced ID 0x" << std::setw(2) << (uint32_t)traceID << "; ";
343 logger.LogMsg(oss.str());
344
345 err = mapper.ReadTargetMemory(read_address, ranges.ranges[range].trcID, OCSD_MEM_SPACE_EL1N, &num_bytes_read, p_local_buff);
346
347 mem_callback_occurred = (bool)(PrevAccCallbackCount != AccCallbackCount);
348 if (mem_callback_occurred)
349 oss.str("MemCB read; ");
350 else
351 oss.str("No MemCB; ");
352 logger.LogMsg(oss.str());
353
354 if (err != OCSD_OK) {
355 oss.str("");
356 oss << "Error reading target memory\n";
357 logger.LogMsg(oss.str());
358 log_error(ocsdError(OCSD_ERR_SEV_ERROR, err, oss.str()));
359 pass = false;
360 goto exit_test;
361 }
362
363 if (num_bytes_read != 4) {
364 oss.str("");
365 oss << "Read Fail: Requested bytes not found (4 != " << num_bytes_read << ")\n";
366 logger.LogMsg(oss.str());
367 pass = false;
368 goto exit_test;
369 }
370
371 if (expected_val != read_val) {
372 oss.str("");
373 oss << "Read Fail: value read mismatch; 0x" << std::hex << read_val << " != 0x" << expected_val << "\n";
374 logger.LogMsg(oss.str());
375 pass = false;
376 goto exit_test;
377 }
378
379 if (callback && !mem_callback_occurred) {
380 oss.str("");
381 oss << "Read Fail: Expected callback to access memory\n";
382 logger.LogMsg(oss.str());
383 pass = false;
384 goto exit_test;
385 }
386
387 if (!callback && mem_callback_occurred) {
388 oss.str("");
389 oss << "Read Fail: Unexpected callback to access memory\n";
390 logger.LogMsg(oss.str());
391 pass = false;
392 goto exit_test;
393 }
394
395 if (pass) {
396 oss.str("\n");
397 logger.LogMsg(oss.str());
398 }
399
400 exit_test:
401 return pass;
402 }
403
test_trcid_cache_mem_cb()404 void test_trcid_cache_mem_cb()
405 {
406 TrcMemAccCB CBAcc;
407 test_range_array_t ranges;
408 int passed = 0, failed = 0;
409 std::ostringstream oss;
410 ocsd_err_t err;
411 int read_test_idx = 1;
412
413
414 log_test_start(__FUNCTION__);
415
416 // set up the ranges
417 ranges.num_ranges = 6;
418 ranges.ranges = new test_range_t[6];
419
420 // 1st range 0x0000, EL1N, trcID 0x10 - 1st CPU
421 set_test_range(ranges.ranges[0], 0x0000, BLOCK_SIZE_BYTES, (const uint8_t*)&el01_ns_blocks[0], OCSD_MEM_SPACE_EL1N, 0x10);
422 // 2nd range 0x0000, EL1N, trcID 0x11 - 2nd cpu, same addresses, different data.
423 set_test_range(ranges.ranges[1], 0x0000, BLOCK_SIZE_BYTES, (const uint8_t*)&el01_ns_blocks[1], OCSD_MEM_SPACE_EL1N, 0x11);
424 // 2nd range 0x8000, EL2N, trcID 0x10 - 2nd cpu, same addresses, different data.
425 set_test_range(ranges.ranges[2], 0x8000, BLOCK_SIZE_BYTES, (const uint8_t*)&el2_ns_blocks[0], OCSD_MEM_SPACE_EL2, 0x10);
426 // 2nd range 0x10000, EL2N, trcID 0x11 - 2nd cpu,
427 set_test_range(ranges.ranges[3], 0x10000, BLOCK_SIZE_BYTES, (const uint8_t*)&el2_ns_blocks[1], OCSD_MEM_SPACE_EL2, 0x11);
428 // 2nd range 0x0000, EL1 realm, trcID 0x10 - cpu 1 realm
429 set_test_range(ranges.ranges[4], 0x0000, BLOCK_SIZE_BYTES, (const uint8_t*)&el01_r_blocks[0], OCSD_MEM_SPACE_EL1R, 0x10);
430 // 2nd range 0x0000, EL2 realm, trcID 0x11 - 2nd cpu - realm .
431 set_test_range(ranges.ranges[5], 0x0000, BLOCK_SIZE_BYTES, (const uint8_t*)&el2_r_blocks[0], OCSD_MEM_SPACE_EL2R, 0x11);
432
433 // add the callback to the mapper
434 CBAcc.initAccessor(0, 0xFFFFFFFF, OCSD_MEM_SPACE_ANY);
435 CBAcc.setCBIDIfFn(TestMemAccCB, (void*)&ranges);
436 err = mapper.AddAccessor(&CBAcc, 0);
437 if (err != OCSD_OK) {
438 log_error(ocsdError(OCSD_ERR_SEV_ERROR, err, "Failed to set callback memory accessor"));
439 failed++;
440 goto cleanup;
441 }
442
443 // run some tests
444 // initial read - should callback and load cache page
445 read_and_check_from_range(read_test_idx++, 0, ranges, 0, true) ? passed++ : failed++;
446
447 // next read - should not callback but use cache
448 read_and_check_from_range(read_test_idx++, 0, ranges, 0x10, false) ? passed++ : failed++;
449
450 // different cpu - same address - should callback for cache load
451 read_and_check_from_range(read_test_idx++, 1, ranges, 0x10, true) ? passed++ : failed++;
452
453 // different cpu - same address - use cache
454 read_and_check_from_range(read_test_idx++, 1, ranges, 0x10, false) ? passed++ : failed++;
455
456
457 // clean up mapper
458 cleanup:
459 mapper.RemoveAllAccessors();
460 tests_passed += passed;
461 tests_failed += failed;
462 delete[] ranges.ranges;
463
464 log_test_end(__FUNCTION__, passed, failed);
465 }
466
467 /************************************************************************
468 * Test trcID specific memory regions - using callback function.
469 * Emulates clinets such as perf where memory regions change over the
470 * trace run as tasks switched in and out. Tests caching mechanisms in
471 * mapper.
472 */
473
474 #define TEST_ADDR_COMMON 0x000000
475 #define TEST_ADDR_EL1N 0x008000
476 #define TEST_ADDR_EL2 0x010000
477 #define TEST_ADDR_EL1S 0x018000
478 #define TEST_ADDR_EL2S 0x020000
479 #define TEST_ADDR_EL3 0x028000
480 #define TEST_ADDR_EL1R 0x030000
481 #define TEST_ADDR_EL2R 0x038000
482 #define TEST_ADDR_EL3R 0x040000
483
read_and_check_value(ocsd_vaddr_t addr,const uint8_t * p_block_buffer,ocsd_mem_space_acc_t space)484 bool read_and_check_value(ocsd_vaddr_t addr, const uint8_t* p_block_buffer, ocsd_mem_space_acc_t space)
485 {
486 ocsd_err_t err;
487 uint32_t read_val, check_val, num_bytes;
488 std::ostringstream oss;
489 std::string memSpaceStr;
490
491
492 TrcMemAccessorBase::getMemAccSpaceString(memSpaceStr, space);
493 oss << "Read Test: Address 0x" << std::hex << std::setw(8) << std::setfill('0') << addr << "; ";
494 oss << std::setw(4) << std::setfill(' ') << memSpaceStr << ";" ;
495 logger.LogMsg(oss.str());
496
497
498 num_bytes = 4;
499 err = mapper.ReadTargetMemory(addr, 0, space, &num_bytes, (uint8_t*)&read_val);
500 if (err != OCSD_OK) {
501 log_error(ocsdError(OCSD_ERR_SEV_ERROR, err, "Failed to read from mapper"));
502 return false;
503 }
504
505 check_val = *((uint32_t *)p_block_buffer);
506 if (check_val != read_val)
507 {
508 oss.str("");
509 oss << "Read Fail: value read mismatch; 0x" << std::hex << read_val << " != 0x" << check_val << "\n";
510 logger.LogMsg(oss.str());
511 return false;
512 }
513
514 oss.str("");
515 oss << " [0x" << std::hex << std::setw(8) << std::setfill('0') << read_val << "]\n";
516 logger.LogMsg(oss.str());
517 return true;
518 }
519
test_mem_spaces()520 void test_mem_spaces()
521 {
522 ocsd_err_t err;
523 int passed = 0, failed = 0;
524 std::ostringstream oss;
525
526
527 log_test_start(__FUNCTION__);
528
529 // check each memory space, 8 of them, and a each block.
530 #define NUM_ACCS (NUM_BLOCKS * 8)
531 TrcMemAccBufPtr accs[NUM_ACCS];
532
533 // set-up accessors - block 0 in each space is the same - the next will have no overlap
534 accs[0].initAccessor(TEST_ADDR_COMMON, (const uint8_t*)&el01_ns_blocks[0], BLOCK_SIZE_BYTES);
535 accs[0].setMemSpace(OCSD_MEM_SPACE_EL1N);
536 accs[1].initAccessor(TEST_ADDR_EL1N, (const uint8_t*)&el01_ns_blocks[1], BLOCK_SIZE_BYTES);
537 accs[1].setMemSpace(OCSD_MEM_SPACE_EL1N);
538
539 accs[2].initAccessor(TEST_ADDR_COMMON, (const uint8_t*)&el2_ns_blocks[0], BLOCK_SIZE_BYTES);
540 accs[2].setMemSpace(OCSD_MEM_SPACE_EL2);
541 accs[3].initAccessor(TEST_ADDR_EL2, (const uint8_t*)&el2_ns_blocks[1], BLOCK_SIZE_BYTES);
542 accs[3].setMemSpace(OCSD_MEM_SPACE_EL2);
543
544 accs[4].initAccessor(TEST_ADDR_COMMON, (const uint8_t*)&el01_s_blocks[0], BLOCK_SIZE_BYTES);
545 accs[4].setMemSpace(OCSD_MEM_SPACE_EL1S);
546 accs[5].initAccessor(TEST_ADDR_EL1S, (const uint8_t*)&el01_s_blocks[1], BLOCK_SIZE_BYTES);
547 accs[5].setMemSpace(OCSD_MEM_SPACE_EL1S);
548
549 accs[6].initAccessor(TEST_ADDR_COMMON, (const uint8_t*)&el2_s_blocks[0], BLOCK_SIZE_BYTES);
550 accs[6].setMemSpace(OCSD_MEM_SPACE_EL2S);
551 accs[7].initAccessor(TEST_ADDR_EL2S, (const uint8_t*)&el2_s_blocks[1], BLOCK_SIZE_BYTES);
552 accs[7].setMemSpace(OCSD_MEM_SPACE_EL2S);
553
554 accs[8].initAccessor(TEST_ADDR_COMMON, (const uint8_t*)&el3_blocks[0], BLOCK_SIZE_BYTES);
555 accs[8].setMemSpace(OCSD_MEM_SPACE_EL3);
556 accs[9].initAccessor(TEST_ADDR_EL3, (const uint8_t*)&el3_blocks[1], BLOCK_SIZE_BYTES);
557 accs[9].setMemSpace(OCSD_MEM_SPACE_EL3);
558
559 accs[10].initAccessor(TEST_ADDR_COMMON, (const uint8_t*)&el01_r_blocks[0], BLOCK_SIZE_BYTES);
560 accs[10].setMemSpace(OCSD_MEM_SPACE_EL1R);
561 accs[11].initAccessor(TEST_ADDR_EL1R, (const uint8_t*)&el01_r_blocks[1], BLOCK_SIZE_BYTES);
562 accs[11].setMemSpace(OCSD_MEM_SPACE_EL1R);
563
564 accs[12].initAccessor(TEST_ADDR_COMMON, (const uint8_t*)&el2_r_blocks[0], BLOCK_SIZE_BYTES);
565 accs[12].setMemSpace(OCSD_MEM_SPACE_EL2R);
566 accs[13].initAccessor(TEST_ADDR_EL2R, (const uint8_t*)&el2_r_blocks[1], BLOCK_SIZE_BYTES);
567 accs[13].setMemSpace(OCSD_MEM_SPACE_EL2R);
568
569 accs[14].initAccessor(TEST_ADDR_COMMON, (const uint8_t*)&el3_root_blocks[0], BLOCK_SIZE_BYTES);
570 accs[14].setMemSpace(OCSD_MEM_SPACE_ROOT);
571 accs[15].initAccessor(TEST_ADDR_EL3R, (const uint8_t*)&el3_root_blocks[1], BLOCK_SIZE_BYTES);
572 accs[15].setMemSpace(OCSD_MEM_SPACE_ROOT);
573
574 // add accessors to mapper.
575 for (int i = 0; i < NUM_ACCS; i++) {
576 err = mapper.AddAccessor(&accs[i], 0);
577 if (err != OCSD_OK) {
578 log_error(ocsdError(OCSD_ERR_SEV_ERROR, err, "Failed to set callback memory accessor"));
579 failed++;
580 }
581 else
582 passed++;
583 }
584
585 // test a bunch of reads - use specific space then check match if more global spaces are used.
586 oss.str("Test EL1N registered block\n");
587 logger.LogMsg(oss.str());
588 read_and_check_value(TEST_ADDR_COMMON, (const uint8_t*)&el01_ns_blocks[0], OCSD_MEM_SPACE_EL1N) ? passed++ : failed++;
589 read_and_check_value(TEST_ADDR_EL1N, (const uint8_t*)&el01_ns_blocks[1], OCSD_MEM_SPACE_EL1N) ? passed++ : failed++;
590 read_and_check_value(TEST_ADDR_EL1N, (const uint8_t*)&el01_ns_blocks[1], OCSD_MEM_SPACE_N) ? passed++ : failed++;
591 read_and_check_value(TEST_ADDR_EL1N, (const uint8_t*)&el01_ns_blocks[1], OCSD_MEM_SPACE_ANY) ? passed++ : failed++;
592
593 oss.str("Test EL1N registered block\n");
594 logger.LogMsg(oss.str());
595 read_and_check_value(TEST_ADDR_COMMON, (const uint8_t*)&el2_ns_blocks[0], OCSD_MEM_SPACE_EL2) ? passed++ : failed++;
596 read_and_check_value(TEST_ADDR_EL2, (const uint8_t*)&el2_ns_blocks[1], OCSD_MEM_SPACE_EL2) ? passed++ : failed++;
597 read_and_check_value(TEST_ADDR_EL2, (const uint8_t*)&el2_ns_blocks[1], OCSD_MEM_SPACE_N) ? passed++ : failed++;
598 read_and_check_value(TEST_ADDR_EL2, (const uint8_t*)&el2_ns_blocks[1], OCSD_MEM_SPACE_ANY) ? passed++ : failed++;
599
600 oss.str("Test EL1S registered block\n");
601 logger.LogMsg(oss.str());
602 read_and_check_value(TEST_ADDR_COMMON, (const uint8_t*)&el01_s_blocks[0], OCSD_MEM_SPACE_EL1S) ? passed++ : failed++;
603 read_and_check_value(TEST_ADDR_EL1S, (const uint8_t*)&el01_s_blocks[1], OCSD_MEM_SPACE_EL1S) ? passed++ : failed++;
604 read_and_check_value(TEST_ADDR_EL1S, (const uint8_t*)&el01_s_blocks[1], OCSD_MEM_SPACE_S) ? passed++ : failed++;
605 read_and_check_value(TEST_ADDR_EL1S, (const uint8_t*)&el01_s_blocks[1], OCSD_MEM_SPACE_ANY) ? passed++ : failed++;
606
607 oss.str("Test EL2S registered block\n");
608 logger.LogMsg(oss.str());
609 read_and_check_value(TEST_ADDR_COMMON, (const uint8_t*)&el2_s_blocks[0], OCSD_MEM_SPACE_EL2S) ? passed++ : failed++;
610 read_and_check_value(TEST_ADDR_EL2S, (const uint8_t*)&el2_s_blocks[1], OCSD_MEM_SPACE_EL2S) ? passed++ : failed++;
611 read_and_check_value(TEST_ADDR_EL2S, (const uint8_t*)&el2_s_blocks[1], OCSD_MEM_SPACE_S) ? passed++ : failed++;
612 read_and_check_value(TEST_ADDR_EL2S, (const uint8_t*)&el2_s_blocks[1], OCSD_MEM_SPACE_ANY) ? passed++ : failed++;
613
614 oss.str("Test EL3 registered block\n");
615 logger.LogMsg(oss.str());
616 read_and_check_value(TEST_ADDR_COMMON, (const uint8_t*)&el3_blocks[0], OCSD_MEM_SPACE_EL3) ? passed++ : failed++;
617 read_and_check_value(TEST_ADDR_EL3, (const uint8_t*)&el3_blocks[1], OCSD_MEM_SPACE_EL3) ? passed++ : failed++;
618 read_and_check_value(TEST_ADDR_EL3, (const uint8_t*)&el3_blocks[1], OCSD_MEM_SPACE_S) ? passed++ : failed++;
619 read_and_check_value(TEST_ADDR_EL3, (const uint8_t*)&el3_blocks[1], OCSD_MEM_SPACE_ANY) ? passed++ : failed++;
620
621 oss.str("Test EL1R registered block\n");
622 logger.LogMsg(oss.str());
623 read_and_check_value(TEST_ADDR_COMMON, (const uint8_t*)&el01_r_blocks[0], OCSD_MEM_SPACE_EL1R) ? passed++ : failed++;
624 read_and_check_value(TEST_ADDR_EL1R, (const uint8_t*)&el01_r_blocks[1], OCSD_MEM_SPACE_EL1R) ? passed++ : failed++;
625 read_and_check_value(TEST_ADDR_EL1R, (const uint8_t*)&el01_r_blocks[1], OCSD_MEM_SPACE_R) ? passed++ : failed++;
626 read_and_check_value(TEST_ADDR_EL1R, (const uint8_t*)&el01_r_blocks[1], OCSD_MEM_SPACE_ANY) ? passed++ : failed++;
627
628 oss.str("Test EL2R registered block\n");
629 logger.LogMsg(oss.str());
630 read_and_check_value(TEST_ADDR_COMMON, (const uint8_t*)&el2_r_blocks[0], OCSD_MEM_SPACE_EL2R) ? passed++ : failed++;
631 read_and_check_value(TEST_ADDR_EL2R, (const uint8_t*)&el2_r_blocks[1], OCSD_MEM_SPACE_EL2R) ? passed++ : failed++;
632 read_and_check_value(TEST_ADDR_EL2R, (const uint8_t*)&el2_r_blocks[1], OCSD_MEM_SPACE_R) ? passed++ : failed++;
633 read_and_check_value(TEST_ADDR_EL2R, (const uint8_t*)&el2_r_blocks[1], OCSD_MEM_SPACE_ANY) ? passed++ : failed++;
634
635 oss.str("Test ROOT registered block\n");
636 logger.LogMsg(oss.str());
637 read_and_check_value(TEST_ADDR_COMMON, (const uint8_t*)&el3_root_blocks[0], OCSD_MEM_SPACE_ROOT) ? passed++ : failed++;
638 read_and_check_value(TEST_ADDR_EL3R, (const uint8_t*)&el3_root_blocks[1], OCSD_MEM_SPACE_ROOT) ? passed++ : failed++;
639 read_and_check_value(TEST_ADDR_EL3R, (const uint8_t*)&el3_root_blocks[1], OCSD_MEM_SPACE_ANY) ? passed++ : failed++;
640
641 // clear for this test
642 mapper.RemoveAllAccessors();
643
644 // test access more global from specific - set ANY, N S and R spaces
645 accs[0].initAccessor(TEST_ADDR_COMMON, (const uint8_t*)&el01_ns_blocks[0], BLOCK_SIZE_BYTES);
646 accs[0].setMemSpace(OCSD_MEM_SPACE_ANY);
647 accs[1].initAccessor(TEST_ADDR_EL1N, (const uint8_t*)&el01_ns_blocks[1], BLOCK_SIZE_BYTES);
648 accs[1].setMemSpace(OCSD_MEM_SPACE_N);
649 accs[2].initAccessor(TEST_ADDR_EL2, (const uint8_t*)&el2_ns_blocks[0], BLOCK_SIZE_BYTES);
650 accs[2].setMemSpace(OCSD_MEM_SPACE_S);
651 accs[3].initAccessor(TEST_ADDR_EL3, (const uint8_t*)&el2_ns_blocks[1], BLOCK_SIZE_BYTES);
652 accs[3].setMemSpace(OCSD_MEM_SPACE_R);
653
654 for (int i = 0; i < 4; i++) {
655 err = mapper.AddAccessor(&accs[i], 0);
656 if (err != OCSD_OK) {
657 log_error(ocsdError(OCSD_ERR_SEV_ERROR, err, "Failed to set callback memory accessor"));
658 failed++;
659 }
660 else
661 passed++;
662 }
663
664 // for ANY space should match all other spaces
665 uint32_t offset = 0;
666 oss.str("Test ANY registered block\n");
667 logger.LogMsg(oss.str());
668 read_and_check_value(TEST_ADDR_COMMON + offset, ((const uint8_t*)&el01_ns_blocks[0]) +offset, OCSD_MEM_SPACE_EL1N) ? passed++ : failed++;
669 offset += 4;
670 read_and_check_value(TEST_ADDR_COMMON + offset, ((const uint8_t*)&el01_ns_blocks[0]) + offset, OCSD_MEM_SPACE_EL2) ? passed++ : failed++;
671 offset += 4;
672 read_and_check_value(TEST_ADDR_COMMON + offset, ((const uint8_t*)&el01_ns_blocks[0]) + offset, OCSD_MEM_SPACE_EL1S) ? passed++ : failed++;
673 offset += 4;
674 read_and_check_value(TEST_ADDR_COMMON + offset, ((const uint8_t*)&el01_ns_blocks[0]) + offset, OCSD_MEM_SPACE_EL2S) ? passed++ : failed++;
675 offset += 4;
676 read_and_check_value(TEST_ADDR_COMMON + offset, ((const uint8_t*)&el01_ns_blocks[0]) + offset, OCSD_MEM_SPACE_EL3) ? passed++ : failed++;
677 offset += 4;
678 read_and_check_value(TEST_ADDR_COMMON + offset, ((const uint8_t*)&el01_ns_blocks[0]) + offset, OCSD_MEM_SPACE_EL1R) ? passed++ : failed++;
679 offset += 4;
680 read_and_check_value(TEST_ADDR_COMMON + offset, ((const uint8_t*)&el01_ns_blocks[0]) + offset, OCSD_MEM_SPACE_EL2R) ? passed++ : failed++;
681 offset += 4;
682 read_and_check_value(TEST_ADDR_COMMON + offset, ((const uint8_t*)&el01_ns_blocks[0]) + offset, OCSD_MEM_SPACE_S) ? passed++ : failed++;
683 offset += 4;
684 read_and_check_value(TEST_ADDR_COMMON + offset, ((const uint8_t*)&el01_ns_blocks[0]) + offset, OCSD_MEM_SPACE_N) ? passed++ : failed++;
685 offset += 4;
686 read_and_check_value(TEST_ADDR_COMMON + offset, ((const uint8_t*)&el01_ns_blocks[0]) + offset, OCSD_MEM_SPACE_R) ? passed++ : failed++;
687 offset += 4;
688 read_and_check_value(TEST_ADDR_COMMON + offset, ((const uint8_t*)&el01_ns_blocks[0]) + offset, OCSD_MEM_SPACE_ROOT) ? passed++ : failed++;
689
690 oss.str("Test Any N registered block\n");
691 logger.LogMsg(oss.str());
692 offset = 0;
693 read_and_check_value(TEST_ADDR_EL1N + offset, ((const uint8_t*)&el01_ns_blocks[1]) + offset, OCSD_MEM_SPACE_EL1N) ? passed++ : failed++;
694 offset += 4;
695 read_and_check_value(TEST_ADDR_EL1N + offset, ((const uint8_t*)&el01_ns_blocks[1]) + offset, OCSD_MEM_SPACE_EL2) ? passed++ : failed++;
696 offset += 4;
697 read_and_check_value(TEST_ADDR_EL1N + offset, ((const uint8_t*)&el01_ns_blocks[1]) + offset, OCSD_MEM_SPACE_N) ? passed++ : failed++;
698
699 oss.str("Test Any S registered block\n");
700 logger.LogMsg(oss.str());
701 offset = 0;
702 read_and_check_value(TEST_ADDR_EL2 + offset, ((const uint8_t*)&el2_ns_blocks[0]) + offset, OCSD_MEM_SPACE_EL1S) ? passed++ : failed++;
703 offset += 4;
704 read_and_check_value(TEST_ADDR_EL2 + offset, ((const uint8_t*)&el2_ns_blocks[0]) + offset, OCSD_MEM_SPACE_EL2S) ? passed++ : failed++;
705 offset += 4;
706 read_and_check_value(TEST_ADDR_EL2 + offset, ((const uint8_t*)&el2_ns_blocks[0]) + offset, OCSD_MEM_SPACE_EL3) ? passed++ : failed++;
707 offset += 4;
708 read_and_check_value(TEST_ADDR_EL2 + offset, ((const uint8_t*)&el2_ns_blocks[0]) + offset, OCSD_MEM_SPACE_S) ? passed++ : failed++;
709
710 oss.str("Test Any R registered block\n");
711 logger.LogMsg(oss.str());
712 offset = 0;
713 read_and_check_value(TEST_ADDR_EL3 + offset, ((const uint8_t*)&el2_ns_blocks[1]) + offset, OCSD_MEM_SPACE_EL1R) ? passed++ : failed++;
714 offset += 4;
715 read_and_check_value(TEST_ADDR_EL3 + offset, ((const uint8_t*)&el2_ns_blocks[1]) + offset, OCSD_MEM_SPACE_EL2R) ? passed++ : failed++;
716 offset += 4;
717 read_and_check_value(TEST_ADDR_EL3 + offset, ((const uint8_t*)&el2_ns_blocks[1]) + offset, OCSD_MEM_SPACE_R) ? passed++ : failed++;
718 offset += 4;
719
720 // clean up
721 mapper.RemoveAllAccessors();
722 tests_passed += passed;
723 tests_failed += failed;
724 log_test_end(__FUNCTION__, passed, failed);
725 }
726
727 /************************************************************************
728 * main program
729 */
main(int argc,char * argv[])730 int main(int argc, char* argv[])
731 {
732 std::ostringstream oss;
733
734 if (!process_cmd_line_logger_opts(argc, argv))
735 {
736 std::cout << "Bad logger command line options\nProgram Exiting\n";
737 return -1;
738 }
739
740 // init the loggers.
741 logger.setLogOpts(logOpts);
742 logger.setLogFileName(logfileName.c_str());
743 err_log.initErrorLogger(OCSD_ERR_SEV_INFO);
744 err_log_handle = err_log.RegisterErrorSource("MEMACCTEST");
745 err_log.setOutputLogger(&logger);
746
747 oss << "OpenCSD memory access tests.\n";
748 oss << "----------------------------\n\n";
749 oss << "Library Version : " << ocsdVersion::vers_str() << "\n\n";
750 logger.LogMsg(oss.str());
751
752 // set up test data
753 populate_all_blocks();
754
755 // init the mapper
756 mapper.setErrorLog(&err_log);
757 mapper.enableCaching(true);
758
759 // call the test routines
760 test_overlap_regions();
761
762 test_trcid_cache_mem_cb();
763
764 test_mem_spaces();
765
766
767 oss.str("");
768 oss << "\n*** Memory access tests complete.***\nPassed: " << tests_passed << "; Failed: " << tests_failed << "\n";
769 logger.LogMsg(oss.str());
770 return (tests_failed == 0) ? 0 : -2;
771 }
772