/* IBM_PROLOG_BEGIN_TAG * This is an automatically generated prolog. * * $Source: src/usr/pnor/test/pnorrptest.H $ * * IBM CONFIDENTIAL * * COPYRIGHT International Business Machines Corp. 2011-2012 * * p1 * * Object Code Only (OCO) source materials * Licensed Internal Code Source Materials * IBM HostBoot Licensed Internal Code * * The source code for this program is not published or other- * wise divested of its trade secrets, irrespective of what has * been deposited with the U.S. Copyright Office. * * Origin: 30 * * IBM_PROLOG_END_TAG */ #ifndef __PNORRPTEST_H #define __PNORRPTEST_H /** * @file pnorrptest.H * * @brief Test case for PNOR Resource Provider */ #include #include #include #include #include #include #include "../pnorrp.H" extern trace_desc_t* g_trac_pnor; class PnorRpTest : public CxxTest::TestSuite { public: /** * @brief PNOR RP test - Section Info * Check that the section info at least appears somewhat valid. */ void test_sectionInfo(void) { TRACFCOMP(g_trac_pnor, "PnorRpTest::test_sectionInfo> Start" ); uint64_t fails = 0; uint64_t total = 0; PNOR::SectionInfo_t info; errlHndl_t errhdl = NULL; //Only check required sections. Some are currently optional due to //Storage limitations in VPO. const PNOR::SectionId testSections[] = { PNOR::TOC, /**< Table of Contents */ PNOR::HB_EXT_CODE, /**< Hostboot Extended Image */ PNOR::HB_DATA, /**< Hostboot Data */ PNOR::DIMM_JEDEC_VPD, /**< DIMM JEDEC VPD */ PNOR::MODULE_VPD, /**< Module VPD */ }; uint64_t numSections = 5; for( uint64_t idx = 0; idx < numSections; idx++) { total++; errhdl = PNOR::getSectionInfo( testSections[idx], PNOR::CURRENT_SIDE, info ); if( errhdl ) { TRACFCOMP(g_trac_pnor, "PnorRpTest::test_sectionInfo> ERROR : getSectionInfo returned error for %d : RC=%X", testSections[idx], errhdl->reasonCode() ); TS_FAIL( "PnorRpTest::test_getSectionInfo> ERROR : Unexpected error log" ); fails++; errlCommit(errhdl,PNOR_COMP_ID); } // Look for non-zero size total++; if( info.size == 0 ) { TRACFCOMP(g_trac_pnor, "PnorRpTest::test_sectionInfo> ERROR : zero size for section %d : id=%d, actual=%d", testSections[idx], info.id, info.size ); TS_FAIL( "PnorRpTest::test_getSectionInfo> ERROR : Zero Size" ); fails++; } // Look for vaddr in appropriate section of virtual memory total++; if( info.vaddr < PnorRP::BASE_VADDR ) { TRACFCOMP(g_trac_pnor, "PnorRpTest::test_sectionInfo> ERROR : Virtual Addr section %d Not in appropriate range: id=%d, actual=%d", testSections[idx], info.id, info.vaddr ); TS_FAIL( "PnorRpTest::test_getSectionInfo> ERROR : Invalid vaddr" ); fails++; } } TRACFCOMP(g_trac_pnor, "PnorRpTest::test_sectionInfo> %d/%d fails", fails, total ); }; /** * @brief PNOR RP test - Read/Write Page * Use message interface to read and write individual pages */ void test_messageReadWrite(void) { return; //this fails with the new message ids TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> Start" ); uint64_t fails = 0; uint64_t total = 0; int rc = 0; msg_q_t mq = PnorRP::getInstance().iv_msgQ; // allocate some space to play with uint64_t data1_r[PAGESIZE/sizeof(uint64_t)]; uint64_t data2_r[PAGESIZE/sizeof(uint64_t)]; uint64_t data_tmp[PAGESIZE/sizeof(uint64_t)]; // use the HB_DATA as scratch space PNOR::SectionInfo_t info; PNOR::getSectionInfo( PNOR::HB_DATA, PNOR::SIDE_A, info ); msg_t* msg = msg_allocate(); // read the first page total++; msg->type = MSG_MM_RP_READ; msg->data[1] = (uint64_t)data1_r; //data[1] = address to copy into (user buffer) msg->data[0] = info.vaddr; //data[0] = address to copy from (effective address) rc = msg_sendrecv( mq, msg ); if( rc ) { TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(READ):1" ); TS_FAIL( "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(READ):1, rc=%d", rc ); fails++; } // read the second page total++; msg->type = MSG_MM_RP_READ; msg->data[1] = (uint64_t)data2_r; //data[1] = address to copy into (user buffer) msg->data[0] = info.vaddr + PAGESIZE; //data[0] = address to copy from (effective address) rc = msg_sendrecv( mq, msg ); if( rc ) { TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(READ):2" ); TS_FAIL( "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(READ):2, rc=%d", rc ); fails++; } // put some data into the first page for( uint64_t x = 0; x < (PAGESIZE/sizeof(uint64_t)); x++ ) { data_tmp[x] = x; } // write the changed page back out total++; msg->type = MSG_MM_RP_WRITE; msg->data[1] = (uint64_t)data_tmp; //data[1] = address to copy from (user buffer) msg->data[0] = info.vaddr; //data[0] = address to copy into (effective address) rc = msg_sendrecv( mq, msg ); if( rc ) { TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(WRITE):1" ); TS_FAIL( "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(WRITE):1, rc=%d", rc ); fails++; } // read the first page again total++; msg->type = MSG_MM_RP_READ; msg->data[1] = (uint64_t)data1_r; //data[1] = address to copy into (user buffer) msg->data[0] = info.vaddr; //data[0] = address to copy from (effective address) rc = msg_sendrecv( mq, msg ); if( rc ) { TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(READ):3" ); TS_FAIL( "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(READ):3, rc=%d", rc ); fails++; } // compare to what we wrote total++; if( memcmp( data_tmp, data1_r, PAGESIZE ) ) { TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> ERROR : Data mismatch in page0" ); TS_FAIL( "PnorRpTest::test_messageReadWrite> ERROR : Data mismatch in page0" ); fails++; uint64_t* act_data = data1_r; for( uint64_t x = 0; x < 4; x++ ) { TRACFCOMP( g_trac_pnor, "ACT:%2d : %.16X %.16X %.16X %.16X", x, act_data[x*4], act_data[x*4+1], act_data[x*4+2], act_data[x*4+3] ); TRACFCOMP( g_trac_pnor, "EXP:%2d : %.16X %.16X %.16X %.16X", x, act_data[x*4], act_data[x*4+1], act_data[x*4+2], act_data[x*4+3] ); } } // read the second page again total++; msg->type = MSG_MM_RP_READ; msg->data[1] = (uint64_t)data_tmp; //data[1] = address to copy into (user buffer) msg->data[0] = info.vaddr + PAGESIZE; //data[0] = address to copy from (effective address) rc = msg_sendrecv( mq, msg ); if( rc ) { TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(READ):4" ); TS_FAIL( "PnorRpTest::test_messageReadWrite> ERROR : error from msg_sendrecv(READ):4, rc=%d", rc ); fails++; } // compare to what we read the first time total++; if( memcmp( data_tmp, data2_r, PAGESIZE ) ) { TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> ERROR : Data mismatch in page1" ); TS_FAIL( "PnorRpTest::test_messageReadWrite> ERROR : Data mismatch in page1" ); fails++; uint64_t* act_data = data_tmp; for( uint64_t x = 0; x < 4; x++ ) { TRACFCOMP( g_trac_pnor, "ACT:%2d : %.16X %.16X %.16X %.16X", x, act_data[x*4], act_data[x*4+1], act_data[x*4+2], act_data[x*4+3] ); TRACFCOMP( g_trac_pnor, "EXP:%2d : %.16X %.16X %.16X %.16X", x, act_data[x*4], act_data[x*4+1], act_data[x*4+2], act_data[x*4+3] ); } } msg_free(msg); TRACFCOMP(g_trac_pnor, "PnorRpTest::test_messageReadWrite> %d/%d fails", fails, total ); }; /** * @brief PNOR RP test - Read/Write Addresses * do read/modify/write/read to different virtual addresses */ void test_AddrReadWrite(void) { return; //@todo - enable this after Task 3445 TRACFCOMP( g_trac_pnor, "PnorRpTest::test_AddrReadWrite> Start" ); uint64_t fails = 0; uint64_t total = 0; uint64_t* ptr = NULL; // read a bunch of addresses ptr = new uint64_t[16]; for( uint64_t addr = 0; addr < 20; addr += 2048 ) // loop at 2K (half-page) intervals { TRACFCOMP( g_trac_pnor, "PnorRpTest::test_AddrReadWrite> addr=%X", addr ); total++; memcpy( ptr, (void*)(0x80000000+addr), 16*sizeof(uint64_t) ); } delete[] ptr; // setup a bunch of interesting addresses to read/write from uint64_t test_addrs[] = { 0x8007E690, // chip0-HB_DATA 0x8207E690, // chip1-HB_DATA 0x8007E790, // chip0-HB_DATA+0x100 0x8207E890, // chip1-HB_DATA+0x200 }; uint64_t test_vals[] = { 0x1111222233334444, 0xA5A5A5A5A5A5A5A5, 0x5566778899AABBCC, 0xBEEFBEEFBEEFBEEF, }; // loop around and do alternating writes and reads for( uint64_t x = 0; x < (sizeof(test_addrs)/sizeof(test_addrs[0])); x++ ) { TRACFCOMP( g_trac_pnor, "PnorRpTest::test_AddrReadWrite> x1=%d", x ); total++; ptr = (uint64_t*) test_addrs[x]; *ptr = test_vals[x]; // verify we can write data if( *ptr != test_vals[x] ) { TRACFCOMP( g_trac_pnor, "PnorRpTest::test_AddrReadWrite> ERROR : Data mismatch in first write of address 0x%p : exp=0x%X, act=0x%X", ptr, test_vals[x], *ptr ); TS_FAIL( "PnorRpTest::test_AddrReadWrite> ERROR : Data mismatch in first write" ); fails++; } } for( uint64_t x = 0; x < (sizeof(test_addrs)/sizeof(test_addrs[0])); x++ ) { TRACFCOMP( g_trac_pnor, "PnorRpTest::test_AddrReadWrite> x2=%d", x ); total++; ptr = (uint64_t*) test_addrs[x]; // make sure we don't write on top of each other if( *ptr != test_vals[x] ) { TRACFCOMP( g_trac_pnor, "PnorRpTest::test_AddrReadWrite> ERROR : Data mismatch in second read of address 0x%p : exp=0x%X, act=0x%X", ptr, test_vals[x], *ptr ); TS_FAIL( "PnorRpTest::test_AddrReadWrite> ERROR : Data mismatch in second read" ); fails++; } } TRACFCOMP(g_trac_pnor, "PnorRpTest::test_AddrReadWrite> %d/%d fails", fails, total ); }; //@todo - import config data from build and compare to section info }; #endif