• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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