From c154ece8068c2f0fc366235ba952003e08df48a1 Mon Sep 17 00:00:00 2001 From: Missy Connell Date: Tue, 26 Mar 2013 09:23:58 -0500 Subject: TCE support RTC:36952 Change-Id: Icc1e88df4e8a8b50cae4fd9fe3789e98be61604e Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/4297 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III --- src/include/usr/runtime/runtime_reasoncodes.H | 17 +- src/include/usr/runtime/tceif.H | 83 +++ src/include/usr/vmmconst.h | 6 + src/usr/runtime/makefile | 3 +- src/usr/runtime/tce.C | 781 ++++++++++++++++++++++++++ src/usr/runtime/tce.H | 169 ++++++ src/usr/runtime/test/makefile | 46 +- src/usr/runtime/test/tcetest.H | 391 +++++++++++++ 8 files changed, 1471 insertions(+), 25 deletions(-) create mode 100644 src/include/usr/runtime/tceif.H create mode 100644 src/usr/runtime/tce.C create mode 100644 src/usr/runtime/tce.H create mode 100644 src/usr/runtime/test/tcetest.H diff --git a/src/include/usr/runtime/runtime_reasoncodes.H b/src/include/usr/runtime/runtime_reasoncodes.H index 4a8f8c0ae..6d3df5bf2 100644 --- a/src/include/usr/runtime/runtime_reasoncodes.H +++ b/src/include/usr/runtime/runtime_reasoncodes.H @@ -38,6 +38,14 @@ namespace RUNTIME MOD_HDATSERVICE_GET_STANDALONE_SECTION = 0x06, /**< hdatservice.C */ MOD_HDATSERVICE_GET_HOST_DATA_SECTION = 0x07, /**< hdatservice.C */ MOD_HDATSERVICE_VERIFY_HDAT_ADDRESS = 0x08, /**< hdatservice.C */ + MOD_TCE_CREATE = 0x09, /**< tce.C */ + MOD_TCE_INIT_HDW = 0x0A, /**< tce.C */ + MOD_TCE_ALLOCATE = 0x0B, /**< tce.C */ + MOD_TCE_DEALLOCATE = 0x0C, /**< tce.C */ + MOD_TCE_INIT = 0x0D, /**< tce.C */ + MOD_TCE_MAP = 0x0E, /**< tce.C */ + + }; enum RuntimeReasonCode @@ -55,7 +63,14 @@ namespace RUNTIME RC_INVALID_ADDRESS = RUNTIME_COMP_ID | 0x0B, RC_INVALID_SECTION = RUNTIME_COMP_ID | 0x0C, RC_CANNOT_MAP_MEMORY3 = RUNTIME_COMP_ID | 0x0D, - + RC_TCE_INVALID_SIZE = RUNTIME_COMP_ID | 0x0E, + RC_TCE_ADDR_NOT_ALIGNED = RUNTIME_COMP_ID | 0x0F, + RC_TCE_INIT_NOT_RUN = RUNTIME_COMP_ID | 0x10, + RC_TCE_DEV_MAP_FAIL = RUNTIME_COMP_ID | 0x11, + RC_TCE_DEV_UNMAP_FAIL = RUNTIME_COMP_ID | 0x12, + RC_TCE_NO_ACTIVE_PSI = RUNTIME_COMP_ID | 0x13, + RC_TCE_NOT_ENOUGH_FREE_ENTRIES = RUNTIME_COMP_ID | 0x14, + RC_TCE_ENTRY_NOT_CONTIGUOUS = RUNTIME_COMP_ID | 0x15, }; }; diff --git a/src/include/usr/runtime/tceif.H b/src/include/usr/runtime/tceif.H new file mode 100644 index 000000000..9dcc7ca14 --- /dev/null +++ b/src/include/usr/runtime/tceif.H @@ -0,0 +1,83 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/runtime/tceif.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* 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 otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __TCEIF_H +#define __TCEIF_H + +#include +#include +#include +#include + + +namespace TCE +{ + /** + * @brief Responsible for initalizing the TCE entries + * + * @return errl - Return Error Handle if failed. + * + */ + errlHndl_t createTceTable(); + + /** + * @brief Responsible for setting up the Processors to point to the TCE + * table + * + * @return errl - Return Error Handle if failed. + * + */ + errlHndl_t initTceInHdw(); + + /** + * @brief Responsible for allocating TCE Entries + * + * @param[in] i_startingAddress - Starting address to TCE + * @param[in] i_size - Size of the address space + * @param[out] startingToken - Starting Entry into the table. + * (this is an offset into the array based on the + * TCE index * PAGESIZE. Each TCE entry maps to a + * pagesize of memory) + * + * Note: Must run createTceTable and InitTceInHdw or allocate will not work + * + * @return errl - Return Error Handle if failed. + * + */ + errlHndl_t allocateTces(uint64_t startingAddress, uint64_t size, uint64_t& + startingToken); + + /** + * @brief Responsible for deallocating TCE Entries + * + * @param[in] i_startingToken - Token indicating the starting entry to + * remove + * @param[in] i_size - Size of memory space to remove TCE entries + * associated + * + * @return errl - Return Error Handle if fatal failure occurred. + * + */ + errlHndl_t deallocateTces(uint64_t startingToken, uint64_t size); +}; + +#endif diff --git a/src/include/usr/vmmconst.h b/src/include/usr/vmmconst.h index 3a0526347..544f0d32f 100644 --- a/src/include/usr/vmmconst.h +++ b/src/include/usr/vmmconst.h @@ -149,4 +149,10 @@ enum BlockPriority #define DUMP_TEST_MEMORY_ADDR (HSVC_TEST_MEMORY_ADDR + HSVC_TEST_MEMORY_SIZE) #define DUMP_TEST_MEMORY_SIZE (4*MEGABYTE) +/** Location of the TCE Table */ +#define TCE_TABLE_ADDR (90*MEGABYTE) + +// The size if 512K bytes of entries each uint64_t or 8 bytes in size. +#define TCE_TABLE_SIZE ((512*KILOBYTE)*sizeof(uint64_t)) + #endif /* _VMMCONST_H */ diff --git a/src/usr/runtime/makefile b/src/usr/runtime/makefile index 8482289a0..7f3e5d495 100644 --- a/src/usr/runtime/makefile +++ b/src/usr/runtime/makefile @@ -30,7 +30,8 @@ ROOTPATH = ../../.. MODULE = runtime -OBJS = populate_attributes.o hdatservice.o fakepayload.o + +OBJS = populate_attributes.o hdatservice.o fakepayload.o tce.o SUBDIRS = test.d diff --git a/src/usr/runtime/tce.C b/src/usr/runtime/tce.C new file mode 100644 index 000000000..619364671 --- /dev/null +++ b/src/usr/runtime/tce.C @@ -0,0 +1,781 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/runtime/tce.C $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* 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 otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __TCE_C +#define __TCE_C + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "tce.H" +#include +#include + +trace_desc_t* g_trac_tce = NULL; +TRAC_INIT(&g_trac_tce, "TCE", 4*KILOBYTE); + + +namespace TCE +{ + /*************************************************************************/ + // External Interface. + // NAME: createTceTable Table. + // Responsible for initalizing the TCE entries + // + /*************************************************************************/ + errlHndl_t createTceTable() + { + return Singleton::instance().createTceTable(); + }; + + /************************************************************************/ + // External Interface. + // NAME: InitTceInHdw + // Responsible for setting up the Processors to point to the TCE table + // + /************************************************************************/ + errlHndl_t initTceInHdw() + { + return Singleton::instance().initTceInHdw(); + }; + + /************************************************************************/ + // External Interface: + // NAME: allocateTces + // Responsible for allocating TCE Entries + // + /************************************************************************/ + errlHndl_t allocateTces(uint64_t startingAddress, uint64_t size, uint64_t& + startingToken) + { + + return Singleton::instance().allocateTces(startingAddress, + size, + startingToken); + }; + + /************************************************************************/ + // External Interface: + // NAME: deallocateTces + // Responsible for deallocating TCE Entries + // + /************************************************************************/ + errlHndl_t deallocateTces(uint64_t startingToken, uint64_t size) + { + return Singleton::instance().deallocateTces(startingToken, + size); + }; + +}; + + /************************************************************************/ + // + // NAME: TceMgr + // Constructor - set up Tce Table pointers + // + /************************************************************************/ + TceMgr::TceMgr(uint64_t i_tableAddr, uint64_t i_tableSize) + :tceEntryInit(0) + ,tceTableVaPtr(NULL) + ,tceTablePhysAddr(i_tableAddr) + ,maxTceEntries(0) + ,tceTableSize(i_tableSize) + { + maxTceEntries = tceTableSize/(sizeof (uint64_t)); + }; + + /**************************************************************************/ + // + // NAME: mapTceTable + // Utilty to map the Tce Table + // + /**************************************************************************/ + errlHndl_t TceMgr::mapTceTable() + { + errlHndl_t errl = NULL; + + do + { + + // check to make sure the TCE table is not larger than 32M.. + if (tceTableSize > THIRTYTWO_MB) + { + + // TCE table size larger than 32M.. code bug likely as the real + // TCE table is a fixed address and size. + TRACFCOMP(g_trac_tce,"TceMgr::mapTceTable: Table size too large..cannot map."); + + /*@ + * @errortype + * @moduleid RUNTIME::MOD_TCE_MAP + * @reasoncode RUNTIME::RC_TCE_INVALID_SIZE + * @userdata1 Address of the TCE Table + * @userdata2 Size of of the table that is too large? + * @devdesc TCE Table size requested too large. + */ + errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_TCE_MAP, + RUNTIME::RC_TCE_INVALID_SIZE, + tceTablePhysAddr, + tceTableSize); + + break; + + } + + // Is the TCE TABLE Address page aligned? + if (tceTablePhysAddr - ALIGN_PAGE_DOWN(tceTablePhysAddr)!=0) + { + // Address not page aligned + TRACFCOMP(g_trac_tce,"TceMgr::mapTceTable: Table Addr not page aligned."); + + /*@ + * @errortype + * @moduleid RUNTIME::MOD_TCE_MAP + * @reasoncode RUNTIME::RC_TCE_ADDR_NOT_ALIGNED + * @userdata1 Address of the TCE Table + * @userdata2 none + * @devdesc TCE Table not page aligned. + */ + errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_TCE_MAP, + RUNTIME::RC_TCE_ADDR_NOT_ALIGNED, + tceTablePhysAddr, + 0); + + break; + } + + + // If the physical address is less than the VMM size, then the + // address we are mapping in on the heap and is already mapped. + // NOTE: This is needed for testing a TCE table outside of the + // default TCE table location. + if (tceTablePhysAddr < VMM_MEMORY_SIZE) + { + tceTableVaPtr = reinterpret_cast(tceTablePhysAddr); + + } + else + { + // Map the Physical Tce table Pointer + tceTableVaPtr = + reinterpret_cast( + mmio_dev_map(reinterpret_cast(tceTablePhysAddr), + THIRTYTWO_MB)); + + if (tceTableVaPtr == NULL) + { + // Got a bad rc from dev Map + TRACFCOMP(g_trac_tce, "TceMgr::mapTceTable: Device map error."); + + /*@ + * @errortype + * @moduleid RUNTIME::MOD_TCE_MAP + * @reasoncode RUNTIME::RC_TCE_DEV_MAP_FAIL + * @userdata1 Address to be mapped + * @userdata2 return Code from DevMap + * @devdesc Device Map Fail + */ + errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_TCE_MAP, + RUNTIME::RC_TCE_DEV_MAP_FAIL, + tceTablePhysAddr, + tceTableSize); + } + } + }while(0); + + return errl; + } + + /**************************************************************************/ + // + // NAME: createTceTable + // Responsible for initalizing the TCE entries + // + /**************************************************************************/ + errlHndl_t TceMgr::createTceTable() + { + + errlHndl_t errl = NULL; + + TRACFCOMP(g_trac_tce,"TceMgr::creatTceTable: tceTablePhysAddr = %llx tceTableSize = %llx",tceTablePhysAddr, tceTableSize); + + do + { + // Map the Tce Table + errl = mapTceTable(); + + if (errl != NULL) + { + break; + } + + // Zero out the TCE table space. + memset(tceTableVaPtr, 0, tceTableSize); + + // make sure that the memset completes. + sync(); + + }while(0); + + return errl; + }; + + /**************************************************************************/ + // + // NAME: InitTceInHdw + // Responsible for setting up the Processors to point to the TCE table + // + /**************************************************************************/ + errlHndl_t TceMgr::initTceInHdw() + { + errlHndl_t errl = NULL; + + TRACFCOMP(g_trac_tce, + "TceMgr::InitTceInHdw: tceTablePhysAddr = %llx", + tceTablePhysAddr); + do + { + + // Loop through the processors and read the PSI_BRIDGE_ADDR + TARGETING::TargetHandleList l_cpuTargetList; + getAllChips(l_cpuTargetList, TARGETING::TYPE_PROC); + + // Map a device at the PSI_BRIDE_ADDR - + // PSI_BRIDGE_BASE_ADDR + // 0x0003FFFE80000000 + uint64_t *mmio_ptr = NULL; + + // set up the registers for TCE on all procs + for (TARGETING::TargetHandleList::const_iterator + l_cpuIter = l_cpuTargetList.begin(); + l_cpuIter != l_cpuTargetList.end(); + ++l_cpuIter) + { + const TARGETING::Target* l_pTarget = *l_cpuIter; + uint64_t PsiBridgeAddr = + l_pTarget->getAttr(); + + TRACDCOMP(g_trac_tce,"TceMgr::InitTceInHdw:Psi Bridge Addr = %llx huid = %.8X",PsiBridgeAddr, TARGETING::get_huid(l_pTarget)); + + // Check if the PSI_BRIDEG_BASE_ADDR is nonzero.. (could be for + // Tuleta) + if (PsiBridgeAddr != 0) + { + // If the PsiBridgeAddr is not page aligned. assert. + assert((PsiBridgeAddr - ALIGN_PAGE_DOWN(PsiBridgeAddr)) == + 0); + + // Map the device for the PSI_BRIDGE_ADDR + mmio_ptr = + static_cast( + mm_block_map( + reinterpret_cast(PsiBridgeAddr), + PAGESIZE)); + + if (mmio_ptr == NULL) + { + // Got a bad rc from device Map + TRACFCOMP(g_trac_tce, "TceMgr::_createTceTable: Device map error."); + + /*@ + * @errortype + * @moduleid RUNTIME::MOD_TCE_INIT_HDW + * @reasoncode RUNTIME::RC_TCE_DEV_MAP_FAIL + * @userdata1 Address to be mapped PsiBridgeAddr + * @userdata2 Tce Phys Addr + * @devdesc PSI Bridge device Map failed + */ + errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_TCE_INIT_HDW, + RUNTIME::RC_TCE_DEV_MAP_FAIL, + PsiBridgeAddr, + tceTablePhysAddr); + break; + } + + + // NOTE>> WILL MAKE DEBUG WHEN DONE TESTING + TRACFCOMP(g_trac_tce,"TceMgr::InitTceInHdw:phys addr = %llx",tceTablePhysAddr); + + // Put the physical TCE addr in PsiBridgeAddr + 18 this is + // byte offset but since we are uin64_t increment 3 double + // words. + *(mmio_ptr + 0x3) = tceTablePhysAddr; + + eieio(); + + // NOTE>> WILL MAKE DEBUG WHEN DONE TESTING + TRACFCOMP(g_trac_tce,"TceMgr::InitTceInHdw:physaddr in Hardware = %llx",*(mmio_ptr + 0x3)); + + // Turn on TCE enable (MMIO offset 0x90) + // the mmio_ptr is uint64_t + *(mmio_ptr + 0x12) = 0x1; + + // NOTE>> WILL MAKE DEBUG WHEN DONE TESTING + TRACFCOMP(g_trac_tce,"TceMgr::InitTceInHdw:Set MMIO offset 0x90 = %llx",*(mmio_ptr + 0x12)); + + // unmap the device.. + uint64_t rc = + mm_block_unmap(reinterpret_cast(mmio_ptr)); + + if (rc != 0) + { + // Got a bad rc from device unmap + TRACFCOMP(g_trac_tce, + "TceMgr::initTce: device unmap error."); + + /*@ + * @errortype + * @moduleid RUNTIME::MOD_TCE_INIT_HDW + * @reasoncode RUNTIME::RC_TCE_DEV_UNMAP_FAIL + * @userdata1 Virtual Addr + * @userdata2 return Code from devUnMap + * @devdesc Device UnMap Failure + */ + errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_TCE_INIT_HDW, + RUNTIME::RC_TCE_DEV_UNMAP_FAIL, + reinterpret_cast(mmio_ptr), + rc); + break; + } + + mmio_ptr = NULL; + } + } + + }while(0); + + // If succsesfull set init to 1 + if (errl == NULL) + { + tceEntryInit = 1; + + // Successfully initialized the TCE table and hardware. + TRACFCOMP(g_trac_tce, "TceMgr::_initTceInHdw: TCE initialized and setup"); + } + + return errl; + } + + + /************************************************************************/ + // + // NAME: allocateTces + // Responsible for allocating TCE Entries + // + /************************************************************************/ + errlHndl_t TceMgr::allocateTces(uint64_t i_startingAddress, + uint64_t i_size, + uint64_t& o_startingToken) + { + errlHndl_t errl = NULL; + + TRACFCOMP(g_trac_tce, + "TceMgr::AllocateTce: start for addr = %llx and size = %llx", + i_startingAddress, i_size); + + // Default the starting Token to invalid Token. + o_startingToken = INVALID_TOKEN_ENTRY; + + do + { + + // Check to see if init was run.. If not then error... + if (!tceEntryInit) + { + // TceInit did not run before allocate was called + TRACFCOMP(g_trac_tce,"TceMgr::AllocateTce: ERROR-initTceInHdw has not run"); + + // error out because allocate was called before INIT.. Could + // possibly just call init here.. but need to verify exactly + // WHEN the init can get called.. + + /*@ + * @errortype + * @moduleid RUNTIME::MOD_TCE_ALLOCATE + * @reasoncode RUNTIME::RC_TCE_INIT_NOT_RUN + * @userdata1 Address to start TCE + * @userdata2 Size of the address space tring to get TCEs + * for. + * @devdesc TCE Table has not been initialized yet + */ + errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_TCE_ALLOCATE, + RUNTIME::RC_TCE_INIT_NOT_RUN, + i_startingAddress, + i_size); + + break; + } + + // Check to see if createTceTable ran before allocate. If not we + // need to make sure the hardware is mapped.. If we are in + // multi-node we would run Create on only 1 node and other node + // could use that table to we don't need to create the table twice. + if (tceTableVaPtr == NULL) + { + // createTceTable has not run + TRACFCOMP(g_trac_tce,"TceMgr::AllocateTce: ERROR - createTceTable has not run so doing the mapping here."); + + errl = mapTceTable(); + + if (errl != NULL) + { + break; + } + } + + //if not page aligned.. expecting a page aligned address passed in + if (i_startingAddress - ALIGN_PAGE_DOWN(i_startingAddress) != 0) + { + TRACFCOMP(g_trac_tce,"TceMgr::AllocateTce: ERROR-Address not page aligned"); + + /*@ + * @errortype + * @moduleid RUNTIME::MOD_TCE_ALLOCATE + * @reasoncode RUNTIME::RC_TCE_ADDR_NOT_ALIGNED + * @userdata1 Address to start TCE + * @userdata2 Size of the address space tring to get TCEs + * for. + * @devdesc The Physical Address for the TCE entry is not + * page aligned. + */ + errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_TCE_ALLOCATE, + RUNTIME::RC_TCE_ADDR_NOT_ALIGNED, + i_startingAddress, + i_size); + + break; + } + + // Calculate the number of TCE entries needed + uint32_t numTcesNeeded = ALIGN_PAGE_DOWN(i_size)/PAGESIZE; + + // If more than the number of TCE entry avail.. error out. + if (numTcesNeeded > maxTceEntries) + { + TRACFCOMP(g_trac_tce,"TceMgr::AllocateTce: ERROR - Too many entries requested"); + + /*@ + * @errortype + * @moduleid RUNTIME::MOD_TCE_ALLOCATE + * @reasoncode RUNTIME::RC_TCE_INVALID_SIZE + * @userdata1 Address to start TCE + * @userdata2 Size of the address space tring to get TCEs + * for. + * @devdesc The size requested is too large for the table + */ + errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_TCE_ALLOCATE, + RUNTIME::RC_TCE_INVALID_SIZE, + i_startingAddress, + i_size); + break; + } + + // Find a first consequetive group of TCE entries requested + int startingIndex = 0; + bool found = false; + + // Start at the beginning and search for the first empty entry + for (uint32_t tceIndex = 0; + tceIndex < maxTceEntries; + tceIndex++) + { + if (!tceTableVaPtr[tceIndex].valid) + { + uint32_t availIndex = 0; + + // if not enough space avail. + if (numTcesNeeded+tceIndex > maxTceEntries) + { + break; + } + for (uint32_t IndexInRow = tceIndex; + IndexInRow < numTcesNeeded + tceIndex; + IndexInRow++) + { + // If the entry is Not valid.. then the entry is + // available + if (!tceTableVaPtr[IndexInRow].valid) + { + // Increment availIndex + availIndex++; + } + // found a valid entry so need to start the count over. + else + { + // increment past the tce entries we already checked + tceIndex = IndexInRow+1; + + // reset the avail index + availIndex = 0; + + break; + } + + // If we found enough consecutive TCE entires + if (availIndex >= numTcesNeeded) + { + // set the starting index + startingIndex = tceIndex; + // mark it found + found = true; + break; + } + } + // break out and update the table + if (found) + { + break; + } + + // did not find consecutive TCE entries so continue. + } + } + + + if (found) + { + // Do a for loop here to loop through the number of TCE entries + // and set the valid bits.. read address changes.. have to add + // PAGESIZE to each address + for (uint32_t i = startingIndex; + i maxTceEntries)) + { + // User passed in an invalid token, do not do a deallocate and + // return + TRACFCOMP(g_trac_tce,"TceMgr::DeallocateTce: ERROR -invalid Token = %lx, No deallocate.", i_startingToken); + + break; + } + + if (startingIndex+numTcesNeeded > maxTceEntries) + { + TRACFCOMP(g_trac_tce,"TceMgr::DeallocateTce: ERROR - request goes past the end of the tce table"); + + /*@ + * @errortype + * @moduleid RUNTIME::MOD_TCE_DEALLOCATE + * @reasoncode RUNTIME::RC_TCE_INVALID_SIZE + * @userdata1 starting index + * @userdata2 number of TCEs needed for this request + * @devdesc The size requested is too large for the table + * space avail starting at the Token passed in. + */ + errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_TCE_DEALLOCATE, + RUNTIME::RC_TCE_INVALID_SIZE, + startingIndex, + numTcesNeeded); + + errlCommit(errl,RUNTIME_COMP_ID); + + numTcesNeeded = numTcesNeeded - + ((startingIndex+numTcesNeeded)-maxTceEntries); + + TRACFCOMP(g_trac_tce,"TceMgr::DeallocateTce: ERROR - clearing from index = %d to end of table", startingIndex); + + } + + // Currently do not check for valid entries.. Just clear as + // requested. + uint64_t realAddress = 0; + + for (uint32_t tceIndex = startingIndex; + tceIndex < (startingIndex + numTcesNeeded); + tceIndex++) + { + if (tceIndex != startingIndex) + { + // check that the address space is contiguous + if (((tceTableVaPtr[tceIndex].realPageNumber - + realAddress) != PAGESIZE) && + ((tceTableVaPtr[tceIndex].realPageNumber - + realAddress) != 0)) + { + isContiguous = false; + } + } + + realAddress = tceTableVaPtr[tceIndex].realPageNumber; + + // Clear out the TCE entry to 0 + tceTableVaPtr[tceIndex].WholeTceEntry = 0; + } + + if (!isContiguous) + { + // We know the range to delete is not contingous.. the Token and + // size passed in crosses past individual allocates. We will + // create error log to indicate that but will clear number of + // entries requested by caller + TRACFCOMP(g_trac_tce,"TceMgr::DeallocateTce: ERROR - request was not contiguous TCE entries"); + + /*@ + * @errortype + * @moduleid RUNTIME::MOD_TCE_DEALLOCATE + * @reasoncode RUNTIME::RC_TCE_ENTRY_NOT_CONTIGUOUS + * @userdata1 i_startingToken + * @userdata2 Size of the address space trying to deallocate + * @devdesc The deallocate went across TCE Allocate space. + */ + errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + RUNTIME::MOD_TCE_DEALLOCATE, + RUNTIME::RC_TCE_ENTRY_NOT_CONTIGUOUS, + i_startingToken, + i_size); + + errlCommit(errl,RUNTIME_COMP_ID); + + } + + }while(0); + + TRACFCOMP(g_trac_tce,"TceMgr::DeAllocateTce: COMPLETE for Token = %llx for size = %llx",i_startingToken, i_size); + + return errl; + } + + /**************************************************************************/ + // + // NAME: ~TceMgr + // Destructor + // + /**************************************************************************/ + TceMgr::~TceMgr() + { + // If the If phys addr and VA table address match and If the physical + // addr is not less than VMM memory size we need unmap + // If it was less than VMM Memory it was already mapped outside of the + // TCE scope and doesn't need to be unmapped here. + if ((tceTablePhysAddr != reinterpret_cast(tceTableVaPtr)) && + (!(tceTablePhysAddr < VMM_MEMORY_SIZE))) + { + if (tceTableVaPtr!= NULL) + { + // Unmap the tceTableVaPtr + uint64_t rc = + mm_block_unmap(reinterpret_cast(tceTableVaPtr)); + + if (rc != 0) + { + TRACFCOMP(g_trac_tce,"TceMgr::~TceMgr: ERROR - Unmap failed rc = %d", rc); + } + } + } + else + { + + TRACFCOMP(g_trac_tce,"TceMgr::~TceMgr: No Unmap required. testing.."); + } + } + +#endif diff --git a/src/usr/runtime/tce.H b/src/usr/runtime/tce.H new file mode 100644 index 000000000..b2a7b82c5 --- /dev/null +++ b/src/usr/runtime/tce.H @@ -0,0 +1,169 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/usr/runtime/tce.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2013 */ +/* */ +/* 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 otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __TCE_H +#define __TCE_H + +#include +#include +#include +#include + + + + +struct TceEntry +{ + // TCE Table + union + { + uint64_t WholeTceEntry; + struct { + uint64_t realPageNumber :52; // real page number + uint64_t valid :1; // The tces is valid for IO + uint64_t reserved :9; // reserved bits + uint64_t writeAccess :1; // Write access allowed + uint64_t readAccess :1; // Read access allowed + }; + + }; +}; + + +/** @class TceMgr + * @brief Responsible for managing the TCE entries + * + */ + class TceMgr + { + + private: + /** Indicator of TCEs being intialized */ + int tceEntryInit; + + /** Pointer to the Mapped TCE Table */ + TceEntry *tceTableVaPtr; + /** physical address of the TCE Table */ + uint64_t tceTablePhysAddr; + + //** Max number of TCE entries - via size*/ + uint64_t maxTceEntries; + + /** size of the Tce Table */ + uint64_t tceTableSize; + + + /** + * @brief Responsible for mapping the TCE Table + * + * @return errlHndl_t - Return error log if unsuccessful + * + */ + errlHndl_t mapTceTable(void); + + public: + /** + * @brief Constructor. Initializes instance variables. + * @param[in/default] i_tableAddr - Starting address of the TCE + * table.. Default address is TCE_TABLE_ADDR. This was added + * for testing TCE entries and not using the "real" table + * @param[in/default] i_tableSize - Size of the TCE table. Default value + * is TCE_TABLE_SIZE + */ + TceMgr(uint64_t i_tableAddr = TCE_TABLE_ADDR, + uint64_t i_tableSize = TCE_TABLE_SIZE); + + /** + * Destructor. + * No action necessary. + */ + ~TceMgr(); + + /** Max TCE Entries for the TCE Table */ + enum + { + NUM_TCE_TABLE_ENTRIES = 0x80000, // 512k entries + }; + + enum + { + INVALID_TOKEN_ENTRY = 0xFFFFFFFFFFFFFFFF, + }; + + + + /** + * @brief Responsible for initalizing the TCE Table and mapping the + * TCEtable + * + * @return errlHndl_t - Return error log if unsuccessful + * + */ + errlHndl_t createTceTable(); + + + /** + * @brief Responsible for setting up the Processors to point to the TCE + * table + * + * @return errlHndl_t - Return error log if unsuccessful + * + */ + errlHndl_t initTceInHdw(); + + + /** + * @brief Responsible for allocating TCE Entries + * + * @param[in] i_startingAddress - Starting address to TCE + * @param[in] i_size - Size of the address space + * @param[out] startingToken - Starting Entry into the table. + * (this is an offset into the array based on the + * TCE index * PAGESIZE. Each TCE entry maps to a + * pagesize of memory) + * + * @return errl - Return Error Handle if failed. + * + */ + errlHndl_t allocateTces(uint64_t i_startingAddress, + uint64_t i_size, + uint64_t& o_startingToken); + + /** + * @brief Responsible for deallocating TCE Entries + * + * @param[in] i_startingToken - Token indicating the starting entry to + * remove + * @param[in] i_size - Size of memory space to remove TCE entries + * associated + * + * @return errl - Return Error Handle if fatal failure occurred. + * + */ + errlHndl_t deallocateTces(uint64_t i_startingToken, + uint64_t i_size); + + + }; + +#endif + diff --git a/src/usr/runtime/test/makefile b/src/usr/runtime/test/makefile index 16f87433a..2f5472dc4 100644 --- a/src/usr/runtime/test/makefile +++ b/src/usr/runtime/test/makefile @@ -1,25 +1,25 @@ -# IBM_PROLOG_BEGIN_TAG -# This is an automatically generated prolog. -# -# $Source: src/usr/runtime/test/makefile $ -# -# IBM CONFIDENTIAL -# -# COPYRIGHT International Business Machines Corp. 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 otherwise -# divested of its trade secrets, irrespective of what has been -# deposited with the U.S. Copyright Office. -# -# Origin: 30 -# -# IBM_PROLOG_END_TAG +# IBM_PROLOG_BEGIN_TAG +# This is an automatically generated prolog. +# +# $Source: src/usr/runtime/test/makefile $ +# +# IBM CONFIDENTIAL +# +# COPYRIGHT International Business Machines Corp. 2012,2013 +# +# 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 otherwise +# divested of its trade secrets, irrespective of what has been +# deposited with the U.S. Copyright Office. +# +# Origin: 30 +# +# IBM_PROLOG_END_TAG ROOTPATH = ../../../.. MODULE = testruntime @@ -31,6 +31,6 @@ EXTRAINCDIR += ${ROOTPATH}/src/include/usr/ecmddatabuffer EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/fapi EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/plat EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/hwp - +EXTRAINCDIR += ${ROOTPATH}/src/include/usr/runtime/ include ${ROOTPATH}/config.mk diff --git a/src/usr/runtime/test/tcetest.H b/src/usr/runtime/test/tcetest.H new file mode 100644 index 000000000..fefbe1867 --- /dev/null +++ b/src/usr/runtime/test/tcetest.H @@ -0,0 +1,391 @@ + +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/runtime/test/tcetest.H $ */ +/* */ +/* IBM CONFIDENTIAL */ +/* */ +/* COPYRIGHT International Business Machines Corp. 2012,2013 */ +/* */ +/* 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 otherwise */ +/* divested of its trade secrets, irrespective of what has been */ +/* deposited with the U.S. Copyright Office. */ +/* */ +/* Origin: 30 */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __TEST_TCETEST_H +#define __TEST_TCETEST_H + +/** + * @file tcetest.H + * + */ + +#include + +#include //for MAGIC +#include +#include +#include +#include +#include "../tce.H" +#include +#include +#include +#include + +extern trace_desc_t* g_trac_tce; + +class TCETest: public CxxTest::TestSuite +{ + public: + void testTCE(void) + { + TRACFCOMP( g_trac_tce, "testTCE> start" ); + errlHndl_t errhdl = NULL; + uint64_t token0 = 0; + uint64_t token1 = 0; + uint64_t token2 = 0; + uint64_t token3 = 0; + uint64_t token4 = 0; + uint64_t token5 = 0; + + uint64_t l_tceTable = + reinterpret_cast(PageManager::allocatePage(4, true)); + + + TceMgr *TceTable = new + TceMgr(l_tceTable+100,100*(sizeof(uint64_t))); + + //--------------------------------------------------- + // TEST 1 - Call Create with unaligned addr + //--------------------------------------------------- + + errhdl = TceTable->createTceTable(); + + if (errhdl == NULL) + { + TRACFCOMP( g_trac_tce,"TestTce: T1: Did not get expected error from CreateTce "); + TS_FAIL("testTcE> T1 Did not get expected error back."); + } + else + { + TRACFCOMP( g_trac_tce,"TestTce: T1: Got expected error unaligedn addr back from CreateTce "); + delete errhdl; + } + + // Since we are not page aligned.. Delete the TceTable + delete TceTable; + + // create new TCE table with the aligned address but with a size too + // large + TceTable = new TceMgr(l_tceTable, THIRTYTWO_MB + PAGESIZE); + + + //--------------------------------------------------- + // TEST 2 - Call create with aligned addr with large addr + //--------------------------------------------------- + errhdl = TceTable->createTceTable(); + + if (errhdl == NULL) + { + TRACFCOMP( g_trac_tce,"TestTce: T2: Did not get expected error from CreateTce "); + TS_FAIL("testTcE> T2 Did not get expected error back."); + } + else + { + TRACFCOMP( g_trac_tce,"TestTce: T2: Got expected error, size > 32M back from CreateTce "); + delete errhdl; + } + + + // Since the size was too big. Delete the TceTable + delete TceTable; + + // create new TCE table with the aligned address and valid size + TceTable = new TceMgr(l_tceTable,100*(sizeof(uint64_t))); + + + //--------------------------------------------------- + // TEST 3 - Call allocate before init. + //--------------------------------------------------- + errhdl = TceTable->allocateTces(0x0, ((16*PAGESIZE)), token0); + + if (errhdl != NULL) + { + delete errhdl; + errhdl = NULL; + } + else + { + TRACFCOMP( g_trac_tce,"TestTCE T3: Did not get back expected error"); + TS_FAIL("testTCE:T3: No error when address not page aligned."); + } + + //--------------------------------------------------- + // TEST 4 - Call create with aligned addr + //--------------------------------------------------- + errhdl = TceTable->createTceTable(); + + if (errhdl != NULL) + { + TRACFCOMP( g_trac_tce, + "TestTce: T4: Got unexpected error from CreateTce "); + TS_FAIL("testTcE> T4 got unexpected error back."); + errlCommit(errhdl,RUNTIME_COMP_ID); + + } + + //--------------------------------------------------- + // TEST 5 - Call init. + //--------------------------------------------------- + + errhdl = TceTable->initTceInHdw(); + + if (errhdl != NULL) + { + TRACFCOMP( g_trac_tce, + "TestTce: T5: Got unexpected error from InitTCEINHdw "); + TS_FAIL("testTcE> T5 got unexpected error back."); + errlCommit(errhdl,RUNTIME_COMP_ID); + + } + + token0 = 0; + + //--------------------------------------------------- + // TEST 6 - trying to allocate too large of size. + //--------------------------------------------------- + errhdl = TceTable->allocateTces(0x0, + (520*KILOBYTE*PAGESIZE), + token0); + + if (errhdl != NULL) + { + delete errhdl; + errhdl = NULL; + } + else + { + TRACFCOMP( g_trac_tce, "testTCE>T6: Did not get expecte error"); + TS_FAIL("testTCE> T6: No errorLog when size too large"); + } + + + //--------------------------------------------------- + // TEST 7 - Address not page aligned. + //--------------------------------------------------- + errhdl = TceTable->allocateTces(0x4140, ((16*PAGESIZE)), token0); + + if (errhdl != NULL) + { + delete errhdl; + errhdl = NULL; + } + else + { + TRACFCOMP( g_trac_tce, "testTCE:T7: Did not get back expected error"); + TS_FAIL("testTCE:T7 No error when addr not page aligned"); + } + + + //--------------------------------------------------- + // TEST 8 - valid address with 8 pages in size + //--------------------------------------------------- + errhdl = TceTable->allocateTces(0x0000000004000000, + PAGESIZE*8, + token1); + + if (errhdl != NULL) + { + TRACFCOMP( g_trac_tce, "testTCE> T8: Got unexpected error "); + TS_FAIL("testTCE> T8 got unexpected error back."); + + errlCommit(errhdl,RUNTIME_COMP_ID); + } + else if (token1 != 0) + { + TRACFCOMP( g_trac_tce, "testTCEs> T8: Did not get back expected Token= %lx", token1); + TS_FAIL("testTCEs> T8 got wrong Token."); + + } + + //--------------------------------------------------- + // TEST 9 - valid address with 16 pages in size + //--------------------------------------------------- + errhdl = TceTable->allocateTces(0x0000000004010000, + PAGESIZE*16, + token2); + + if (errhdl != NULL) + { + TRACFCOMP( g_trac_tce, "testTCE> T9: Got unexpected error "); + TS_FAIL("testTCE> T9 got unexpected error back."); + + errlCommit(errhdl,RUNTIME_COMP_ID); + } + else if (token2 != 0x8000) + { + TRACFCOMP( g_trac_tce, "testTCE> T9: Did not get back expected Token = %lx ", token2); + TS_FAIL("testTCE> T9 got wrong Token."); + } + + + //--------------------------------------------------- + // TEST 10 - valid address with 50 pages in size + //--------------------------------------------------- + errhdl = TceTable->allocateTces(0x0000000004800000, + PAGESIZE*50, + token3); + + if (errhdl != NULL) + { + TRACFCOMP( g_trac_tce, "testTCE> T10: Got unexpected error "); + TS_FAIL("testTCE> T10 got unexpected error back."); + + errlCommit(errhdl,RUNTIME_COMP_ID); + } + else if (token3 != 0x18000) + { + TRACFCOMP( g_trac_tce, "testTCE> T10: Did not get back expected Token = %lx ", token3); + TS_FAIL("testTCE> T10 got wrong Token."); + } + + + //--------------------------------------------------- + // TEST 11 - Deallocate token with 16 pages from above + //--------------------------------------------------- + errhdl = TceTable->deallocateTces(token2, + PAGESIZE*16); + if (errhdl != NULL) + { + TRACFCOMP( g_trac_tce, "testTCE:T11: Got unexpected error "); + TS_FAIL("testTCE:T11 Deallocate got unexpected error"); + + errlCommit(errhdl,RUNTIME_COMP_ID); + } + + + token2 = 0; + + //--------------------------------------------------- + // TEST 12 Allocate 10 pages.. will go into the slot left by the + // previous allocate + //--------------------------------------------------- + errhdl = TceTable->allocateTces(0x0000000004010000, + PAGESIZE*10, + token2); + + if (errhdl != NULL) + { + TRACFCOMP( g_trac_tce, "T12: Got unexpected error "); + TS_FAIL("testAllocateTCEs> T12 Allocate got unexpected error"); + + errlCommit(errhdl,RUNTIME_COMP_ID); + } + else if (token2 != 0x8000) + { + TRACFCOMP( g_trac_tce, "testTCE:T12: Did not get back expected Token = %lx", token2); + TS_FAIL("testTCE:T12: got wrong Token."); + } + + + //--------------------------------------------------- + // TEST 13 Allocate 10 pages.. will have ot pass the 6 slots avail from + // the 16 page dealloate.. So will go past that to find a valid index to + // fit the 20 entries + //--------------------------------------------------- + errhdl = TceTable->allocateTces(0x0000000005010000, + PAGESIZE*20, + token4); + + if (errhdl != NULL) + { + TRACFCOMP( g_trac_tce, "testTCE:T13: Got unexpected error "); + TS_FAIL("testTCE:T13: Allocate got unexpected error"); + + errlCommit(errhdl,RUNTIME_COMP_ID); + } + else if (token4 != 0x4a000) + { + TRACFCOMP( g_trac_tce, "testTCE:T13: Did not get back expected Token = %lx ", token4); + TS_FAIL("testTCE:T10: got wrong Token."); + } + + + + //--------------------------------------------------- + // TEST 14 Allocate 6 pages.. will go into the 6 slots avail from + // the 16 page dealloate.. + //--------------------------------------------------- + errhdl = TceTable->allocateTces(0x0000000006010000, + PAGESIZE*6, + token5); + + if (errhdl != NULL) + { + TRACFCOMP( g_trac_tce, "testTCE:T14: Got unexpected error "); + TS_FAIL("testTCE:T14: Allocate got unexpected error"); + + errlCommit(errhdl,RUNTIME_COMP_ID); + } + else if (token5 != 0x12000) + { + TRACFCOMP( g_trac_tce, "testTCE:T14: Did not get back expected Token "); + TS_FAIL("testTCE:T14: got wrong Token."); + } + + + //--------------------------------------------------- + // TEST 15 Deallocate 20 pages from above + //--------------------------------------------------- + errhdl = TceTable->deallocateTces(token4, PAGESIZE*20); + if (errhdl != NULL) + { + TRACFCOMP( g_trac_tce, "testTCE:T15: Got unexpected error "); + TS_FAIL("testTCE:T15: Deallocate got unexpected error"); + + errlCommit(errhdl,RUNTIME_COMP_ID); + } + + //--------------------------------------------------- + // TEST 16 Deallocate 10 pages from above + //--------------------------------------------------- + errhdl = TceTable->deallocateTces(token2, PAGESIZE*10); + if (errhdl != NULL) + { + TRACFCOMP( g_trac_tce, "testTCE:T16: Got unexpected error "); + TS_FAIL("testTCE:T16: Deallocate got unexpected error"); + + errlCommit(errhdl,RUNTIME_COMP_ID); + } + + //--------------------------------------------------- + // TEST 17 Deallocate Too large of size. No error returned instead the + // code should to end of the TCE table and commit errorlog and return + //--------------------------------------------------- + errhdl = TceTable->deallocateTces(token5, (520*KILOBYTE*PAGESIZE)); + + if (errhdl != NULL) + { + TRACFCOMP( g_trac_tce, "testTCE:T17: Got unexpected error returned"); + TS_FAIL("testTCE:T17: Deallocate got unexpected error"); + + errlCommit(errhdl,RUNTIME_COMP_ID); + } + + TRACFCOMP(g_trac_tce, "testTCE> complete" ); + } + + + +}; +#endif -- cgit v1.2.1