diff options
author | Mike Baiocchi <mbaiocch@us.ibm.com> | 2016-11-04 11:30:17 -0500 |
---|---|---|
committer | William G. Hoffa <wghoffa@us.ibm.com> | 2017-03-08 11:06:34 -0500 |
commit | c3d233bbaf7a2f274147d16edbc080bae0ffd714 (patch) | |
tree | 8058bc8e764135eecc21cdcd1177814dd4e180c8 /src/usr | |
parent | 1301e43641f7d3f315a0abc8112fa88927c9fa9a (diff) | |
download | talos-hostboot-c3d233bbaf7a2f274147d16edbc080bae0ffd714.tar.gz talos-hostboot-c3d233bbaf7a2f274147d16edbc080bae0ffd714.zip |
Hostboot Base TCE Support
This commit adds the base support for hostboot to enable/disable the
use of TCEs. It allows for the creation and managment of a TCE table
and also initializes the P9 processors to use this table.
Change-Id: Idb40f9df5a90d8b7e87b2f5b745cbe7e66109df2
RTC:145071
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/32562
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Reviewed-by: Stephen M. Cprek <smcprek@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Marshall J. Wilks <mjwilks@us.ibm.com>
Reviewed-by: Nicholas E. Bofferding <bofferdn@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Reviewed-by: William G. Hoffa <wghoffa@us.ibm.com>
Diffstat (limited to 'src/usr')
-rw-r--r-- | src/usr/initservice/istepdispatcher/istepdispatcher.C | 8 | ||||
-rw-r--r-- | src/usr/intr/intrrp.H | 23 | ||||
-rw-r--r-- | src/usr/isteps/istep16/call_host_ipl_complete.C | 15 | ||||
-rw-r--r-- | src/usr/isteps/istep21/call_host_runtime_setup.C | 29 | ||||
-rw-r--r-- | src/usr/runtime/makefile | 3 | ||||
-rw-r--r-- | src/usr/runtime/tce.C | 791 | ||||
-rw-r--r-- | src/usr/runtime/tce.H | 169 | ||||
-rw-r--r-- | src/usr/runtime/test/makefile | 3 | ||||
-rw-r--r-- | src/usr/runtime/test/tcetest.H | 391 | ||||
-rw-r--r-- | src/usr/util/makefile | 3 | ||||
-rw-r--r-- | src/usr/util/test/testtcemgr.H | 363 | ||||
-rw-r--r-- | src/usr/util/utiltcemgr.C | 1276 | ||||
-rw-r--r-- | src/usr/util/utiltcemgr.H | 290 |
13 files changed, 1981 insertions, 1383 deletions
diff --git a/src/usr/initservice/istepdispatcher/istepdispatcher.C b/src/usr/initservice/istepdispatcher/istepdispatcher.C index 7ecccaa2f..91306a765 100644 --- a/src/usr/initservice/istepdispatcher/istepdispatcher.C +++ b/src/usr/initservice/istepdispatcher/istepdispatcher.C @@ -2099,9 +2099,11 @@ errlHndl_t IStepDispatcher::handleCoalesceHostMsg() { TRACFCOMP(g_trac_initsvc, ENTER_MRK"IStepDispatcher::handleCoalesceHostMsg"); - // Ensure the library is loaded - errlHndl_t err = VFS::module_load("libestablish_system_smp.so"); + // Ensure the library is loaded + //@TODO RTC:164474 + //errlHndl_t err = VFS::module_load("libestablish_system_smp.so"); + errlHndl_t err = NULL; if (err) { TRACFCOMP(g_trac_initsvc, "handleCoalesceHostMsg: Error loading module, PLID = 0x%x", @@ -2109,7 +2111,7 @@ errlHndl_t IStepDispatcher::handleCoalesceHostMsg() } else { - //@TODO RTC:133831 + //@TODO RTC:164474 //err = ESTABLISH_SYSTEM_SMP::call_host_coalesce_host(); if (err) { diff --git a/src/usr/intr/intrrp.H b/src/usr/intr/intrrp.H index 1788c9760..1d039f21b 100644 --- a/src/usr/intr/intrrp.H +++ b/src/usr/intr/intrrp.H @@ -264,29 +264,6 @@ namespace INTR }; }; - //Derived from 15.8 PSIHB Software Interfaces of the - // P9 Pervasive Workbook - struct PSIHB_SW_INTERFACES_t - { - uint64_t psihbbar; //Host Bridge Base Address Register - 0x0 - uint64_t fspbar; //FSP Base Address Register - 0x8 - uint64_t fspmmr; //FSP Memory Mask Register - 0x10 - uint64_t reserved1; //Unused / Reserved - uint64_t psihbcr; //PSI Host Bridge Ctrl/Status Register - 0x20 - uint64_t psisemr; //PSIHB Status / Error Mask Register - 0x28 - uint64_t reserved2; //Unused / Reserved - uint64_t phbdsr; //PSIHB Debug Setting register - 0x38 - uint64_t phbscr; //PSI Host Bridge Ctrl/Status Register - 0x40 - uint64_t phbccr; //PSI Host Bridge clear ctl/status reg - 0x48 - uint64_t dmaupaddr; //DMA Upper Address Register - 0x50 - uint64_t icr; //Interrupt Control Register - 0x58 - uint64_t esbciaddr; //ESB CI Base Address - 0x60 - uint64_t esbnotifyaddr; //ESB Notification Address - 0x68 - uint64_t ivtofforig; //IVT Offset Origin Register - 0x70 - uint64_t lsiintlevel; //LSI Int Level Register (lab use) - 0x78 - uint64_t lsiintstatus; //LSI Interrupt Status register - 0x80 - }; - //Found in the PC Register Specification Document struct XIVE_IC_THREAD_CONTEXT_t { diff --git a/src/usr/isteps/istep16/call_host_ipl_complete.C b/src/usr/isteps/istep16/call_host_ipl_complete.C index 30857d73c..1242367ef 100644 --- a/src/usr/isteps/istep16/call_host_ipl_complete.C +++ b/src/usr/isteps/istep16/call_host_ipl_complete.C @@ -44,6 +44,7 @@ #include <targeting/attrrp.H> #include <sys/internode.h> #include <runtime/runtime.H> +#include <util/utiltce.H> using namespace ERRORLOG; using namespace TARGETING; @@ -63,6 +64,20 @@ void* call_host_ipl_complete (void *io_pArgs) "call_host_ipl_complete entry" ); do { + // Setup the TCEs needed for the FSP to DMA the PAYLOAD +/* @TODO RTC 168745 - make this call when FSP is ready for TCE Support + * and add check that we're on a FSP system + * NOTE: add check to do this only on FSP-based systems + * l_err = TCE::utilSetupPayloadTces(); + * + * if( l_err ) + * { + * TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + * ERR_MRK"TCE::utilSetupPayloadTces failed"); + * break; + * } + */ + // Initialize the RUNTIME DATA attributes // that HDAT needs to allocate memory for us. // ----------------------------------------- diff --git a/src/usr/isteps/istep21/call_host_runtime_setup.C b/src/usr/isteps/istep21/call_host_runtime_setup.C index 4d4a85220..06b606ab2 100644 --- a/src/usr/isteps/istep21/call_host_runtime_setup.C +++ b/src/usr/isteps/istep21/call_host_runtime_setup.C @@ -37,6 +37,7 @@ #include <runtime/customize_attrs_for_payload.H> #include <targeting/common/util.H> #include <vpd/vpd_if.H> +#include <util/utiltce.H> //SBE interfacing #include <sbeio/sbeioif.H> @@ -254,12 +255,38 @@ void* call_host_runtime_setup (void *io_pArgs) } #endif + // Close PAYLOAD TCEs +/* @TODO RTC 168745 - make this call when FSP is ready for TCE Support + * and add check that we're on a FSP system + * NOTE: move this call to the start of this function + * NOTE: add check to do this only on FSP-based systems + * l_err = TCE::utilClosePayloadTces(); + * if ( l_err ) + * { + * TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + * "Failed TCE::utilClosePayloadTces" ); + * // break from do loop if error occured + * break; + * } + * + * + * // Disable all TCEs + * l_err = TCE::utilDisableTces(); + * if ( l_err ) + * { + * TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, + * "Failed TCE::utilDisableTces" ); + * // break from do loop if error occured + * break; + * } + */ + } while(0); if( l_err ) { TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, - "istep start_payload_failed see plid 0x%x", l_err->plid()); + "istep host_runtime_setup failed see plid 0x%x", l_err->plid()); // Create IStep error log and cross reference error that occurred l_StepError.addErrorDetails( l_err ); diff --git a/src/usr/runtime/makefile b/src/usr/runtime/makefile index 8306eae03..14838e18d 100644 --- a/src/usr/runtime/makefile +++ b/src/usr/runtime/makefile @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2012,2016 +# Contributors Listed Below - COPYRIGHT 2012,2017 # [+] International Business Machines Corp. # # @@ -37,7 +37,6 @@ MODULE = runtime OBJS += populate_hbruntime.o OBJS += hdatservice.o OBJS += fakepayload.o -OBJS += tce.o OBJS += errlud_hdat.o OBJS += customize_attrs_for_payload.o diff --git a/src/usr/runtime/tce.C b/src/usr/runtime/tce.C deleted file mode 100644 index 0bfce6cbb..000000000 --- a/src/usr/runtime/tce.C +++ /dev/null @@ -1,791 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/usr/runtime/tce.C $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* COPYRIGHT International Business Machines Corp. 2013,2014 */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -#ifndef __TCE_C -#define __TCE_C - -#include <trace/interface.H> -#include <errl/errlentry.H> -#include <errl/errlmanager.H> -#include <vmmconst.h> -#include <runtime/tceif.H> -#include <sys/mmio.h> -#include <util/align.H> -#include <sys/mm.h> -#include <targeting/common/commontargeting.H> -#include <targeting/common/utilFilter.H> -#include <kernel/console.H> -#include "tce.H" -#include <runtime/runtime_reasoncodes.H> -#include <assert.h> - -trace_desc_t* g_trac_tce = NULL; -TRAC_INIT(&g_trac_tce, TCE_TRACE_NAME, 4*KILOBYTE); - - -namespace TCE -{ - /*************************************************************************/ - // External Interface. - // NAME: createTceTable Table. - // Responsible for initalizing the TCE entries - // - /*************************************************************************/ - errlHndl_t createTceTable() - { - return Singleton<TceMgr>::instance().createTceTable(); - }; - - /************************************************************************/ - // External Interface. - // NAME: InitTceInHdw - // Responsible for setting up the Processors to point to the TCE table - // - /************************************************************************/ - errlHndl_t initTceInHdw() - { - return Singleton<TceMgr>::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<TceMgr>::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<TceMgr>::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, - true /*Add HB SW Callout*/); - 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, - true /*Add HB SW Callout*/); - 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<TceEntry *>(tceTablePhysAddr); - - } - else - { - // Map the Physical Tce table Pointer - tceTableVaPtr = - reinterpret_cast<TceEntry *>( - mmio_dev_map(reinterpret_cast<void*>(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, - true /*Add HB SW Callout*/); - } - } - }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 - - // <attribute><id>PSI_BRIDGE_BASE_ADDR</id> - // <default>0x0003FFFE80000000</default> - 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<TARGETING::ATTR_PSI_BRIDGE_BASE_ADDR>(); - - 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<uint64_t*>( - mm_block_map( - reinterpret_cast<void*>(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, - true /*Add HB SW Callout*/); - 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<void*>(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<uint64_t>(mmio_ptr), - rc, - true /*Add HB SW Callout*/); - 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, - true /*Add HB SW Callout*/); - errl->collectTrace(TCE_TRACE_NAME,KILOBYTE); - - 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, - true /*Add HB SW Callout*/); - 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, - true /*Add HB SW Callout*/); - 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<numTcesNeeded+startingIndex; - i++) - { - tceTableVaPtr[i].realPageNumber = i_startingAddress + - (i*PAGESIZE); - tceTableVaPtr[i].valid = 1; - tceTableVaPtr[i].writeAccess = 1; - tceTableVaPtr[i].readAccess = 1; - } - - // We are returning offset into the TCE table for the start of - // the first TCE entry. - o_startingToken = startingIndex * PAGESIZE; - - TRACFCOMP(g_trac_tce,"TceMgr::AllocateTce: Token = %llx for addr = %llx and size = %llx",o_startingToken, i_startingAddress, i_size); - } - else // not found means not enough space for request - { - TRACFCOMP(g_trac_tce,"TceMgr::AllocateTce: ERROR -Not enough free entries for this request"); - - /*@ - * @errortype - * @moduleid RUNTIME::MOD_TCE_ALLOCATE - * @reasoncode RUNTIME::RC_TCE_NOT_ENOUGH_FREE_ENTRIES - * @userdata1 Address to start TCE - * @userdata2 Size of the address space trying to get TCEs - * for. - * @devdesc The size requested is too large. - */ - errl = new ERRORLOG::ErrlEntry( - ERRORLOG::ERRL_SEV_UNRECOVERABLE, - RUNTIME::MOD_TCE_ALLOCATE, - RUNTIME::RC_TCE_NOT_ENOUGH_FREE_ENTRIES, - i_startingAddress, - i_size, - true /*Add HB SW Callout*/); - break; - } - }while(0); - - TRACFCOMP(g_trac_tce, "TceMgr::AllocateTce: EXIT"); - - return errl; - } - - - /*************************************************************************/ - // - // NAME: deallocateTces - // Responsible for deallocating TCE Entries - // - /*************************************************************************/ - errlHndl_t TceMgr::deallocateTces(uint64_t i_startingToken, - uint64_t i_size) - { - - errlHndl_t errl = NULL; - bool isContiguous = true; - - TRACFCOMP(g_trac_tce,"TceMgr::DeAllocateTce: START: for Token = %llx for size = %llx",i_startingToken, i_size); - - do - { - // Get number of TCEs needed. - uint32_t numTcesNeeded = ALIGN_PAGE_DOWN(i_size)/PAGESIZE; - uint32_t startingIndex = i_startingToken/PAGESIZE; - - // if the Token passed in equals the default token, or the - // startingIndex is larger than the max number of indexes avail - if ((i_startingToken == INVALID_TOKEN_ENTRY) || - (startingIndex > 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, - true /*Add HB SW Callout*/); - errl->collectTrace(TCE_TRACE_NAME,KILOBYTE); - - 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, - true /*Add HB SW Callout*/); - errl->collectTrace(TCE_TRACE_NAME,KILOBYTE); - errlCommit(errl,RUNTIME_COMP_ID); - break; - } - - }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<uint64_t>(tceTableVaPtr)) && - (!(tceTablePhysAddr < VMM_MEMORY_SIZE))) - { - if (tceTableVaPtr!= NULL) - { - // Unmap the tceTableVaPtr - uint64_t rc = - mm_block_unmap(reinterpret_cast<void*>(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 deleted file mode 100644 index 487a4bf67..000000000 --- a/src/usr/runtime/tce.H +++ /dev/null @@ -1,169 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/usr/runtime/tce.H $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* COPYRIGHT International Business Machines Corp. 2013,2014 */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -#ifndef __TCE_H -#define __TCE_H - -#include <stdint.h> -#include <builtins.h> -#include <errl/errlentry.H> -#include <devicefw/userif.H> - - - - -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 bebc21cd2..02c6ba3e6 100644 --- a/src/usr/runtime/test/makefile +++ b/src/usr/runtime/test/makefile @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2012,2016 +# Contributors Listed Below - COPYRIGHT 2012,2017 # [+] International Business Machines Corp. # # @@ -27,7 +27,6 @@ ROOTPATH = ../../../.. MODULE = testruntime #@TODO RTC 132750 #TESTS += hdatservicetest.H -#TESTS += tcetest.H TESTS += test_customize_attrs_for_payload.H # The testcase depends on the following file, but it is typically only compiled diff --git a/src/usr/runtime/test/tcetest.H b/src/usr/runtime/test/tcetest.H deleted file mode 100644 index 2baa4ab7d..000000000 --- a/src/usr/runtime/test/tcetest.H +++ /dev/null @@ -1,391 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/usr/runtime/test/tcetest.H $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* COPYRIGHT International Business Machines Corp. 2012,2014 */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ - -#ifndef __TEST_TCETEST_H -#define __TEST_TCETEST_H - -/** - * @file tcetest.H - * - */ - -#include <cxxtest/TestSuite.H> - -#include <arch/ppc.H> //for MAGIC -#include <errl/errlmanager.H> -#include <runtime/runtime.H> -#include <targeting/common/commontargeting.H> -#include <runtime/tceif.H> -#include "../tce.H" -#include <util/align.H> -#include <kernel/console.H> -#include <sys/mmio.h> -#include <kernel/pagemgr.H> - -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<uint64_t>(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 diff --git a/src/usr/util/makefile b/src/usr/util/makefile index 70df3b790..0c3e100cb 100644 --- a/src/usr/util/makefile +++ b/src/usr/util/makefile @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2012,2016 +# Contributors Listed Below - COPYRIGHT 2012,2017 # [+] International Business Machines Corp. # # @@ -33,6 +33,7 @@ OBJS += utilfile.o OBJS += utillidmgr.o OBJS += utillidpnor.o OBJS += utilmbox_scratch.o +OBJS += utiltcemgr.o SUBDIRS += test.d SUBDIRS += runtime.d diff --git a/src/usr/util/test/testtcemgr.H b/src/usr/util/test/testtcemgr.H new file mode 100644 index 000000000..904e46c12 --- /dev/null +++ b/src/usr/util/test/testtcemgr.H @@ -0,0 +1,363 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/util/test/testtcemgr.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2012,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#ifndef __TEST_TCETEST_H +#define __TEST_TCETEST_H + +/** + * @file tcetest.H + * + */ + +#include <cxxtest/TestSuite.H> + +#include <errl/errlmanager.H> +#include <targeting/common/commontargeting.H> +#include <util/utiltce.H> +#include <util/util_reasoncodes.H> +#include "../utiltcemgr.H" + +extern trace_desc_t* g_trac_tce; + + +class TCETest: public CxxTest::TestSuite +{ + public: + + // This helper functions retrieves the private member variable + // iv_allocatedAddrs from the Singleton UtilTceMgr class + std::map<uint64_t, uint32_t> getAllocatedAddrsMap(void) + { + std::map<uint64_t, uint32_t> o_map(TCE::getTceManager().iv_allocatedAddrs); + return o_map; + }; + + + // This helper function looks for the position associated with the input + // address in the Singleton's UtilTceMgr::iv_allocatedAddrs + uint32_t getPos(uint64_t i_addr) + { + uint32_t o_pos = 0xFEFEFEFE; // Default for no position found + + auto map = getAllocatedAddrsMap(); + + TRACDCOMP(g_trac_tce,ENTER_MRK"TCETest::getPos: i_addr=0x%llX, map.size=%d", i_addr, map.size()); + + // Debug-only loop + for (auto mapElement : map ) + { + TRACDCOMP(g_trac_tce,"TCETest::getPos: printIvMap: addr=0x%llX, pos=0x%X", mapElement.first, mapElement.second); + } + + // Find i_addr in map; otherwise o_pos = bad default from above + auto map_itr = map.find(i_addr); + if (map_itr != map.end()) + { + o_pos = map_itr->second; + } + + TRACDCOMP(g_trac_tce,EXIT_MRK"TCETest::getPos: i_addr=0x%llX, o_pos=0x%X", i_addr, o_pos); + + return o_pos; + } + + + + void testTCE(void) + { + TRACFCOMP( g_trac_tce, ENTER_MRK"testTCE> start" ); + + errlHndl_t errhdl = nullptr; + + uint64_t fails = 0x0; + uint64_t total = 0x0; + + struct + { + uint64_t addr; // Start address that TCEs Map To + uint64_t size; // Size of memory that TCEs Map To + uint32_t pos; // Starting Entry Position in TCE Table + } testData[] = + { + { 0x00, 16*PAGESIZE, 0x0}, + { 0x0000000004000000, PAGESIZE*8, 0x10}, + { 0x0000000004010000, PAGESIZE*16, 0x18}, + { 0x0000000004800000, PAGESIZE*50, 0x28}, + { 0x0000000004020000, PAGESIZE*10, 0x18}, + { 0x0000000005010000, PAGESIZE*20, 0x5A}, + { 0x0000000006010000, PAGESIZE*6, 0x22}, + }; + + + //--------------------------------------------------- + // TEST 1 - Call Allocate with unaligned addr + //--------------------------------------------------- + ++total; + errhdl = TCE::utilAllocateTces(PAGESIZE+1, PAGESIZE); + + if (errhdl == nullptr) + { + TRACFCOMP( g_trac_tce,"testTCE> T1: Did not get expected error from utilAllocateTces"); + TS_FAIL("testTCE> T1: Did not get expected error back from utilAllocateTces."); + ++fails; + } + else if ( ERRL_GETRC_SAFE(errhdl) == Util::UTIL_TCE_ADDR_NOT_ALIGNED ) + { + TRACFCOMP( g_trac_tce,"testTCE> T1: Got expected error unaligned addr back from utilAllocateTces: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + delete errhdl; + errhdl = nullptr; + } + else + { + TRACFCOMP( g_trac_tce,"testTCE> T1: got unexpected error back from TCE::utilAllocateTces: rc=0x%X, plid=0x%X (expected rc=0x%X)", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl), Util::UTIL_TCE_ADDR_NOT_ALIGNED); + TS_FAIL("testTCE> T1: got unexpected error back from TCE::utilAllocateTces: rc=0x%X, plid=0x%X (expected rc=0x%X)", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl), Util::UTIL_TCE_ADDR_NOT_ALIGNED); + errlCommit(errhdl,UTIL_COMP_ID); + ++fails; + } + + + //--------------------------------------------------- + // TEST 2 - Call create with aligned addr with large size + //--------------------------------------------------- + ++total; + errhdl = TCE::utilAllocateTces(PAGESIZE, 520*KILOBYTE*PAGESIZE); + + if (errhdl == nullptr) + { + TRACFCOMP( g_trac_tce,"testTCE> T2: Did not get expected error from utilAllocateTces"); + TS_FAIL("testTcE> T2: Did not get expected error back from utilAllocateTces."); + ++fails; + } + else if ( ERRL_GETRC_SAFE(errhdl) == Util::UTIL_TCE_INVALID_SIZE ) + { + TRACFCOMP( g_trac_tce,"testTCE> T2: Got expected error of invalid size back from utilAllocateTces: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + delete errhdl; + errhdl = nullptr; + } + else + { + TRACFCOMP( g_trac_tce,"testTCE> T2: got unexpected error back from TCE::utilAllocateTces: rc=0x%X, plid=0x%X (expected rc=0x%X)", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl), Util::UTIL_TCE_ADDR_NOT_ALIGNED); + TS_FAIL("testTCE> T2: got unexpected error back from TCE::utilAllocateTces: rc=0x%X, plid=0x%X (expected rc=0x%X)", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl), Util::UTIL_TCE_INVALID_SIZE); + errlCommit(errhdl,UTIL_COMP_ID); + ++fails; + } + + //--------------------------------------------------- + // TEST 3 - Four allocate calls + // - init will be called under the covers for the first test + //--------------------------------------------------- + for ( size_t i = 0; i <= 3; ++i ) + { + ++total; + errhdl = TCE::utilAllocateTces(testData[i].addr, testData[i].size); + + if (errhdl != nullptr) + { + TRACFCOMP( g_trac_tce,"testTCE> T3-%d: got unexpected error back from TCE::utilAllocateTces: rc=0x%X, plid=0x%X", i, ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + TS_FAIL("testTCE> T3-%d: got unexpected error back from TCE::utilAllocateTces: rc=0x%X, plid=0x%X", i, ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + errlCommit(errhdl,UTIL_COMP_ID); + ++fails; + } + else if (testData[i].pos != + getPos(testData[i].addr)) + { + TRACFCOMP( g_trac_tce,"testTCE> T3-%d: From TCE::utilAllocateTces testData[0].pos=0x%X != map-pos=0x%X", i, testData[i].pos, getPos(testData[i].addr)); + TS_FAIL("testTCE> T3-%d: From TCE::utilAllocateTces testData[0].pos != map-pos", i); + ++fails; + } + } + + //--------------------------------------------------- + // TEST 4 - Deallocate token with 16 pages from above + //--------------------------------------------------- + ++total; + errhdl = TCE::utilDeallocateTces(testData[2].addr, testData[2].size); + + if (errhdl != nullptr) + { + TRACFCOMP( g_trac_tce, "testTCE> T4: Got unexpected error back from TCE::utilDeallocateTces(testData[2].addr=0x%X, testData[2].size=0x%X: error rc=0x%X, plid=0x%X ", testData[2].addr, testData[2].size, ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + TS_FAIL("testTCE> T4: Got unexpected error back from TCE::utilDeallocateTces: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + errlCommit(errhdl,UTIL_COMP_ID); + ++fails; + } + + + //--------------------------------------------------- + // TEST 5: Two Allocates: + // 1) Allocate 10 pages to go into the available slot left by the + // previous deallocate + // 2) Allocate 20 pages that will skip past some available slots + // left by the previous deallocate + //--------------------------------------------------- + for ( size_t i = 0; i <= 1; ++i ) + { + ++total; + errhdl = TCE::utilAllocateTces(testData[i+4].addr, testData[i+4].size); + + if (errhdl != nullptr) + { + TRACFCOMP( g_trac_tce, "testTCE> T5-%d: Got unexpected error back from TCE::utilAllocateTces: rc=0x%X, plid=0x%X", i, ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + TS_FAIL("testTCE> T5-%d: Got unexpected error back from TCE::utilAllocateTces: rc=0x%X, plid=0x%X", i, ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + errlCommit(errhdl,UTIL_COMP_ID); + ++fails; + } + else if (testData[i+4].pos != + getPos(testData[i+4].addr)) + { + TRACFCOMP( g_trac_tce,"testTCE> T5-%d: From TCE::utilAllocateTces testData[%d].pos=0x%X != map-pos=0x%X", i, i+4, testData[i+4].pos, getPos(testData[i+4].addr)); + TS_FAIL("testTCE> T5-%d: From TCE::utilAllocateTces testData[%d].pos != map-pos", i, i+4); + ++fails; + } + } + + //--------------------------------------------------- + // TEST 6 Allocate 6 pages which should go into the 6 + // slots available from the 16 page deallocate + //--------------------------------------------------- + ++total; + errhdl = TCE::utilAllocateTces(testData[6].addr, testData[6].size); + + if (errhdl != nullptr) + { + TRACFCOMP( g_trac_tce,ERR_MRK"testTCE> T6: Got unexpected error back from TCE::utilAllocateTces: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + TS_FAIL("testTCE> T6: Got unexpected error back from TCE::utilAllocateTces: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + errlCommit(errhdl,UTIL_COMP_ID); + ++fails; + } + else if (testData[6].pos != + getPos(testData[6].addr)) + { + TRACFCOMP( g_trac_tce,"testTCE> T6: From TCE::utilAllocateTces testData[6].pos=0x%X != map-pos=0x%X", testData[6].pos, getPos(testData[6].addr)); + TS_FAIL("testTCE> T6: From TCE::utilAllocateTces testData[6].pos != map-pos"); + ++fails; + } + + //--------------------------------------------------- + // TEST 7 Deallocate 20 pages from above + //--------------------------------------------------- + ++total; + errhdl = TCE::utilDeallocateTces(testData[5].addr, testData[5].size); + if (errhdl != nullptr) + { + TRACFCOMP( g_trac_tce,ERR_MRK"testTCE> T7: Got unexpected error back from TCE::utilDeallocateTces: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + TS_FAIL("testTCE> T7: Got unexpected error back from TCE::utilDeallocateTces: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + errlCommit(errhdl,UTIL_COMP_ID); + ++fails; + } + + //--------------------------------------------------- + // TEST 8 Deallocate 10 pages from above + //--------------------------------------------------- + ++total; + errhdl = TCE::utilDeallocateTces(testData[4].addr, testData[4].size); + + if (errhdl != nullptr) + { + TRACFCOMP( g_trac_tce,ERR_MRK"testTCE> T8: Got unexpected error back from TCE::utilDeallocateTces: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + TS_FAIL("testTCE> T8: Got unexpected error back from TCE::utilDeallocateTces: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + errlCommit(errhdl,UTIL_COMP_ID); + ++fails; + } + + + //--------------------------------------------------- + // TEST 9 Deallocate Too large of size. No error returned instead the + // code should go to end of the TCE table and commit errorlog and return + //--------------------------------------------------- + ++total; + errhdl = TCE::utilDeallocateTces(0x0, (520*KILOBYTE*PAGESIZE)); + + if (errhdl != nullptr) + { + TRACFCOMP( g_trac_tce,ERR_MRK"testTCE> T9: Got unexpected error back from TCE::utilDeallocateTces: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + TS_FAIL("testTCE> T9: Got unexpected error back from TCE::utilDeallocateTces: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + errlCommit(errhdl,UTIL_COMP_ID); + ++fails; + } + + //--------------------------------------------------- + // TEST 10 disable TCEs, which should deallocate all existing TCEs + //--------------------------------------------------- + TRACFCOMP( g_trac_tce,"testTCE> 10: Calling TCE::utilDisableTces"); + ++total; + errhdl = TCE::utilDisableTces(); + + if (errhdl != nullptr) + { + TRACFCOMP( g_trac_tce,ERR_MRK"testTCE> 10: Got unexpected error back from TCE::utilDisableTces: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + TS_FAIL("testTCE> T10: Got unexpected error back from TCE::utilDisableTces: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + errlCommit(errhdl,UTIL_COMP_ID); + ++fails; + } + + + /************************************************************/ + /* @TODO RTC 168745: */ + /* Make The PAYLOAD calls here in the testcase for now */ + /* Consider removing when when part of the IPL */ + /************************************************************/ + + TRACFCOMP( g_trac_tce,"testTCE> TA: Calling TCE::utilSetupPayloadTces"); + ++total; + errhdl = TCE::utilSetupPayloadTces(); + + if (errhdl != nullptr) + { + TRACFCOMP( g_trac_tce,ERR_MRK"testTCE> TA: TCE::utilSetupPayloadTces returned unexpected error: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + TS_FAIL("testTCE> TA: TCE::utilSetupPayloadTces returned unexpected error: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + errlCommit(errhdl,UTIL_COMP_ID); + ++fails; + } + + TRACFCOMP( g_trac_tce,"testTCE> TB: Calling TCE::utilClosePayloadTces"); + ++total; + errhdl = TCE::utilClosePayloadTces(); + + if (errhdl != nullptr) + { + TRACFCOMP( g_trac_tce,ERR_MRK"testTCE> TB: TCE::utilClosePayloadTces returned unexpected error: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + TS_FAIL("testTCE> TB: TCE::utilClosePayloadTces returned unexpected error: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + errlCommit(errhdl,UTIL_COMP_ID); + ++fails; + } + + TRACFCOMP( g_trac_tce,"testTCE> TC: Calling TCE::utilDisableTces"); + ++total; + errhdl = TCE::utilDisableTces(); + + if (errhdl != nullptr) + { + TRACFCOMP( g_trac_tce,ERR_MRK"testTCE> TC: TCE::utilDisableTces returned unexpected error: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + TS_FAIL("testTCE> TC: TCE::utilDisableTces returned unexpected error: rc=0x%X, plid=0x%X", ERRL_GETRC_SAFE(errhdl), ERRL_GETPLID_SAFE(errhdl)); + errlCommit(errhdl,UTIL_COMP_ID); + ++fails; + } + + TRACFCOMP(g_trac_tce, EXIT_MRK"testTCE> complete - %d/%d fails", fails, total); + + } + +}; +#endif diff --git a/src/usr/util/utiltcemgr.C b/src/usr/util/utiltcemgr.C new file mode 100644 index 000000000..eb2ee395b --- /dev/null +++ b/src/usr/util/utiltcemgr.C @@ -0,0 +1,1276 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/util/utiltcemgr.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2013,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __UTILTCEMGR_C +#define __UTILTCEMGR_C + +#include <trace/interface.H> +#include <errl/errlentry.H> +#include <errl/errlmanager.H> +#include <util/utiltce.H> +#include <util/align.H> +#include <sys/mmio.h> +#include <sys/mm.h> +#include <errno.h> +#include <targeting/common/commontargeting.H> +#include <targeting/common/utilFilter.H> +#include <kernel/console.H> +#include "utiltcemgr.H" +#include <util/util_reasoncodes.H> +#include <assert.h> +#include <intr/interrupt.H> +#include <limits.h> +#include <hwas/common/hwasCallout.H> +#include <attributetraits.H> +#include <pnor/pnorif.H> +#include <targeting/common/targetservice.H> +#include <devicefw/userif.H> + +trace_desc_t* g_trac_tce = nullptr; +TRAC_INIT(&g_trac_tce, UTILTCE_TRACE_NAME, 4*KILOBYTE); + +// ------------------------ +// Macros for unit testing - leave extra trace enabled for now +#define TRACUCOMP(args...) TRACFCOMP(args) +//#define TRACUCOMP(args...) + + +namespace TCE +{ + +/************************************************************************/ +// Defines +/************************************************************************/ +// @TODO RTC 168745 Currently hardcoded to 128MB when the original plan was +// to use PNOR payloadInfo.size, but that only was 19MB +#define TCE_PAYLOAD_SIZE (128*MEGABYTE) + +// TCE Table Address must be 4MB Aligned +#define TCE_TABLE_ADDRESS_ALIGNMENT (4*MEGABYTE) + +/************************************************************************/ +// External Interface: +// NAME: utilAllocateTces +// Responsible for allocating TCEs +// +/************************************************************************/ +errlHndl_t utilAllocateTces(const uint64_t i_startingAddress, + const size_t i_size) +{ + return Singleton<UtilTceMgr>::instance().allocateTces(i_startingAddress, + i_size); +}; + +/************************************************************************/ +// External Interface: +// NAME: utilDeallocateTces +// Responsible for deallocating TCEs +// +/************************************************************************/ +errlHndl_t utilDeallocateTces(const uint64_t i_startingAddress, + const size_t i_size) +{ + return Singleton<UtilTceMgr>::instance().deallocateTces(i_startingAddress, + i_size); +}; + + +/************************************************************************/ +// External Interface: +// NAME: utilDisableTces +// Responsible for disabling TCE on the system, including +// deallocating TCE Entries and disabling the Processor settings +// +/************************************************************************/ +errlHndl_t utilDisableTces(void) +{ + return Singleton<UtilTceMgr>::instance().disableTces(); +}; + +/************************************************************************/ +// External Interface: +// NAME: getTceManager +// Returns a copy of Singleton<UtilTceMgr>::instance() +// +/************************************************************************/ +UtilTceMgr& getTceManager(void) +{ + return Singleton<UtilTceMgr>::instance(); +}; + +/***********************************************************************************/ +/* Local function to get PAYLOAD base address and size */ +/***********************************************************************************/ +errlHndl_t getPayloadAddrAndSize(uint64_t& o_addr, size_t& o_size) +{ + errlHndl_t errl = nullptr; + + o_addr=0x0; + o_size=0x0; + + do{ + + // Get Target Service and the system target to get ATTR_PAYLOAD_BASE + TARGETING::TargetService& tS = TARGETING::targetService(); + TARGETING::Target* sys = nullptr; + (void) tS.getTopLevelTarget( sys ); + assert(sys, "getPayloadAddrAndSize() system target is NULL"); + + o_addr = sys->getAttr<TARGETING::ATTR_PAYLOAD_BASE>() + * MEGABYTE; // Attribute value in MB + + assert((o_addr % PAGESIZE) == 0, "getPayloadAddrAndSize(): o_addr=0x%.16llX not on page boundary", o_addr); + + // Get PAYLOAD PNOR section info from PNOR RP + PNOR::SectionInfo_t payloadInfo; + errl = getSectionInfo( PNOR::PAYLOAD, //pnorSectionId, + payloadInfo ); + + if(errl) + { + TRACFCOMP( g_trac_tce, ERR_MRK"getPayloadAddrAndSize() Error calling getSectionInfo() rc=0x%.4X", errl->reasonCode() ); + break; + } + + o_size = TCE_PAYLOAD_SIZE; + + } while(0); + + TRACFCOMP( g_trac_tce,EXIT_MRK"getPayloadAddrAndSize(): o_addr=0x%.16llX, o_size=0x%.16llX", o_addr, o_size); + return errl; +} + +errlHndl_t utilSetupPayloadTces(void) +{ + errlHndl_t errl = nullptr; + + uint64_t addr=0x0; + size_t size=0x0; + + do{ + + TRACFCOMP(g_trac_tce,ENTER_MRK"utilSetupPayloadTces(): get Address and Size"); + + errl = getPayloadAddrAndSize(addr, size); + if (errl) + { + TRACFCOMP(g_trac_tce,"utilSetupPayloadTces(): ERROR back from getPayloadAddrAndSize()"); + break; + } + + errl = utilAllocateTces(addr, size); + if (errl) + { + TRACFCOMP(g_trac_tce,"utilSetupPayloadTces(): ERROR back from utilAllocateTces() using addr=0x%.16llX, size=0x%llX", addr, size); + break; + } + + } while(0); + + TRACFCOMP(g_trac_tce,EXIT_MRK"utilSetupPayloadTces(): Address=0x%.16llX, size=0x%X, errl_rc=0x%X", addr, size, ERRL_GETRC_SAFE(errl)); + + return errl; +} + +errlHndl_t utilClosePayloadTces(void) +{ + errlHndl_t errl = nullptr; + + uint64_t addr=0x0; + size_t size=0x0; + + do{ + + TRACFCOMP(g_trac_tce,ENTER_MRK"utilClosePayloadTces(): get Address and Size"); + + errl = getPayloadAddrAndSize(addr, size); + if (errl) + { + TRACFCOMP(g_trac_tce,"utilClosePayloadTces(): ERROR back from getPayloadAddrAndSize()"); + break; + } + + errl = utilDeallocateTces(addr, size); + if (errl) + { + TRACFCOMP(g_trac_tce,"utilClosePayloadTces(): ERROR back from utilDeallocateTces() using addr=0x%.16llX, size=0x%llX", addr, size); + break; + } + + } while(0); + + TRACFCOMP(g_trac_tce,EXIT_MRK"utilClosePayloadTces(): Address=0x%.16llX, size=0x%X, errl_rc=0x%X", addr, size, ERRL_GETRC_SAFE(errl)); + + return errl; +} + + +/************************************************************************/ +// +// NAME: UtilTceMgr +// Constructor - set up Tce Table pointers +// +/************************************************************************/ +UtilTceMgr::UtilTceMgr(const uint64_t i_tableAddr, const size_t i_tableSize) + :iv_isTceHwInitDone(false) + ,iv_isTceTableInitDone(false) + ,iv_tceTableVaAddr(0) + ,iv_tceTablePhysAddr(i_tableAddr) + ,iv_tceEntryCount(0) + ,iv_tceTableSize(i_tableSize) +{ + // Table Address must be 4MB Aligned and default input is TCE_TABLE_ADDR + static_assert( TCE_TABLE_ADDR % TCE_TABLE_ADDRESS_ALIGNMENT == 0,"TCE Table must align on 4 MB boundary"); + assert( i_tableAddr % TCE_TABLE_ADDRESS_ALIGNMENT == 0,"TCE Table must align on 4 MB boundary: 0x%.16llX", i_tableAddr); + + // TCE Entry counts are based on the following assumption + static_assert((sizeof(uint64_t) == sizeof(TceEntry_t)), "TceEntry_t struct must be size of uint64_t)"); + + // i_tableSize must be a multiple of TCE Entries + assert( i_tableSize % sizeof(TceEntry_t) == 0,"TCE Table Size (0x%llX) must be multiple of TceEntry_t size (0x%X))", i_tableSize, sizeof(TceEntry_t)); + + iv_tceEntryCount = iv_tceTableSize/(sizeof (uint64_t)); + + TRACUCOMP(g_trac_tce,"UtilTceMgr::UtilTceMgr: iv_tceTableVaAddr=0x%.16llX, iv_tceTablePhysAddr=0x%.16llX, iv_tceTableSize=0x%llX, iv_tceEntryCount=0x%X, iv_allocatedAddrs,size=%d", iv_tceTableVaAddr, iv_tceTablePhysAddr, iv_tceTableSize, iv_tceEntryCount, iv_allocatedAddrs.size()); + +}; + +/**************************************************************************/ +// +// NAME: createTceTable +// Utilty to map the Tce Table +// +/**************************************************************************/ +errlHndl_t UtilTceMgr::createTceTable() +{ + errlHndl_t errl = nullptr; + + TRACFCOMP(g_trac_tce,ENTER_MRK"UtilTceMgr::createTceTable: iv_tceTableVaAddr=0x%.16llX, iv_tceTablePhysAddr = 0x%.16llX,iv_tceTableSize = 0x%llX, iv_tceEntryCount=0x%X, iv_isTceTableInitDone=%d", iv_tceTableVaAddr, iv_tceTablePhysAddr, iv_tceTableSize, iv_tceEntryCount, iv_isTceTableInitDone); + + do + { + // If init was already run, then skip here + if (iv_isTceTableInitDone) + { + TRACFCOMP(g_trac_tce,"UtilTceMgr::createTceTable: iv_isTceTableInitDone (%d) already true, so skipping init", iv_isTceTableInitDone); + break; + } + + + // check to make sure the TCE table is not larger than Max Table Size + if (iv_tceTableSize > MAX_TCE_TABLE_SIZE) + { + // TCE table size larger than 32M.. code bug likely as the real + // TCE table is a fixed address and size. + TRACFCOMP(g_trac_tce,"UtilTceMgr::createTceTable: Table size 0x%X too large (>0x%llX) - cannot map.", iv_tceTableSize, MAX_TCE_TABLE_SIZE); + + /*@ + * @errortype + * @moduleid Util::UTIL_TCE_CREATE_TABLE + * @reasoncode Util::UTIL_TCE_INVALID_SIZE + * @userdata1 Size of of the table that is too large + * @userdata2 Max TCE Table Size + * @devdesc TCE Table size requested too large. + * @custdesc A problem occurred during the IPL of the system + */ + errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + Util::UTIL_TCE_CREATE_TABLE, + Util::UTIL_TCE_INVALID_SIZE, + iv_tceTableSize, + MAX_TCE_TABLE_SIZE, + true /*Add HB SW Callout*/); + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + break; + + } + + + // Check that iv_tceEntryCount isn't larger than MAX_NUM_TCE_TABLE_ENTRIES + if (iv_tceEntryCount > MAX_NUM_TCE_TABLE_ENTRIES ) + { + // TCE Count is larger than TCE Table Can Support + TRACFCOMP(g_trac_tce,"UtilTceMgr::createTceTable: iv_tceEntryCount 0x%X too large (>0x%llX) - cannot map.", iv_tceEntryCount, MAX_NUM_TCE_TABLE_ENTRIES); + + /*@ + * @errortype + * @moduleid Util::UTIL_TCE_CREATE_TABLE + * @reasoncode Util::UTIL_TCE_INVALID_COUNT + * @userdata1 Number of TCEs Requested + * @userdata2 Max Number of TCEs that TCE Table can hold + * @devdesc TCE Table size requested too large. + * @custdesc A problem occurred during the IPL of the system + */ + errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + Util::UTIL_TCE_CREATE_TABLE, + Util::UTIL_TCE_INVALID_COUNT, + iv_tceEntryCount, + MAX_NUM_TCE_TABLE_ENTRIES, + true /*Add HB SW Callout*/); + + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + break; + } + + // Check that the TCE TABLE Address is aligned on 4MB + if (iv_tceTablePhysAddr % (4*MEGABYTE)) + { + // Address not page aligned + TRACFCOMP(g_trac_tce,ERR_MRK"UtilTceMgr::createTceTable: Table Addr 0x%.16llX not aligned on 4MB Boundary", iv_tceTablePhysAddr); + + /*@ + * @errortype + * @moduleid Util::UTIL_TCE_CREATE_TABLE + * @reasoncode Util::UTIL_TCE_ADDR_NOT_ALIGNED + * @userdata1 Phyiscal Address of the TCE Table + * @userdata2 <unused> + * @devdesc TCE Table not page aligned. + * @custdesc A problem occurred during the IPL of the system + */ + errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + Util::UTIL_TCE_CREATE_TABLE, + Util::UTIL_TCE_ADDR_NOT_ALIGNED, + iv_tceTablePhysAddr, + 0, + true /*Add HB SW Callout*/); + + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + break; + } + + // Allocate Memory for TCE Table + // - Reserve a block of physical memory and get a pointer to + // virtual memory to manipulate it + iv_tceTableVaAddr = reinterpret_cast<uint64_t>(mm_block_map( + reinterpret_cast<void*>(iv_tceTablePhysAddr), + iv_tceTableSize)); + + // Check that a valid Virtual Memory Address was returned + if (reinterpret_cast<void*>(iv_tceTableVaAddr) == nullptr) + { + // Invalid Virtual Address was returned + TRACFCOMP(g_trac_tce,ERR_MRK"UtilTceMgr::createTceTable: mm_block_map for Table Addr 0x%.16llX and size=0x%X returned NULL", iv_tceTablePhysAddr, iv_tceTableSize); + + /*@ + * @errortype + * @moduleid Util::UTIL_TCE_CREATE_TABLE + * @reasoncode Util::UTIL_ERC_BAD_PTR + * @userdata1 Physical Address of the TCE Table + * @userdata2 Requested Size of the TCE Table + * @devdesc TCE Table Could Not Be Block-Mapped + * @custdesc A problem occurred during the IPL of the system + */ + errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + Util::UTIL_TCE_CREATE_TABLE, + Util::UTIL_ERC_BAD_PTR, + iv_tceTablePhysAddr, + iv_tceTableSize, + true /*Add HB SW Callout*/); + + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + break; + } + + // Zero out the TCE Table space + memset(reinterpret_cast<void*>(iv_tceTableVaAddr), 0, iv_tceTableSize); + + // make sure that the memset completes. + sync(); + + }while(0); + + // If succsesfull set init to true + if ((errl == nullptr) && + (iv_isTceTableInitDone == false)) + { + iv_isTceTableInitDone = true; + + // Successfully initialized the TCE table and hardware. + TRACUCOMP(g_trac_tce, "UtilTceMgr::createTceTable: TCE Table initialized and setup: iv_isTceTableInitDone=%d", iv_isTceTableInitDone); + } + + TRACFCOMP(g_trac_tce, EXIT_MRK"UtilTceMgr::createTceTable: iv_tceTableVaAddr=0x%.16llX, iv_tceTablePhysAddr = 0x%.16llX,iv_tceTableSize = 0x%llX, iv_tceEntryCount=0x%X, iv_isTceTableInitDone=%d", iv_tceTableVaAddr, iv_tceTablePhysAddr, iv_tceTableSize, iv_tceEntryCount, iv_isTceTableInitDone); + + return errl; +} + + +/**************************************************************************/ +// +// NAME: initTceInHdw +// Responsible for setting up the Processors to point to the TCE table +// +/**************************************************************************/ +errlHndl_t UtilTceMgr::initTceInHdw() +{ + errlHndl_t errl = nullptr; + + TRACFCOMP(g_trac_tce, ENTER_MRK"UtilTceMgr::initTceInHdw: iv_tceTablePhysAddr = 0x%.16llX, iv_isTceHwInitDone=%d", iv_tceTablePhysAddr, iv_isTceHwInitDone); + + do + { + // If init was already run, then skip here + if (iv_isTceHwInitDone) + { + TRACFCOMP(g_trac_tce,"UtilTceMgr::initTceInHdw: iv_isTceHwInitDone (%d) already true, so skipping init", iv_isTceHwInitDone); + break; + } + + // Loop through the processors and setup PSI Host Bridge for TCE + TARGETING::TargetHandleList l_cpuTargetList; + getAllChips(l_cpuTargetList, TARGETING::TYPE_PROC); + + for ( auto l_pTarget : l_cpuTargetList ) + { + + void * PsiBridgeAddr = nullptr; + INTR::PSIHB_SW_INTERFACES_t * l_psihb_ptr = nullptr; + TarTceAddrRegister_t l_tar; + + // MMIO Map the PSI Host Bridge + errl = mapPsiHostBridge(l_pTarget, PsiBridgeAddr); + if (errl) + { + TRACFCOMP(g_trac_tce,"UtilTceMgr::initTceInHdw: call to mapPsiHostBridge failed with rc=0x%X, plid=0x%X. Committing Log, but continuing the loop", ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + errlCommit( errl, UTIL_COMP_ID ); + continue; + } + + TRACUCOMP(g_trac_tce,"UtilTceMgr::initTceInHdw: Psi Bridge Addr = 0x%.16llX huid = 0x%.8X", PsiBridgeAddr, TARGETING::get_huid(l_pTarget)); + + l_psihb_ptr = reinterpret_cast<INTR::PSIHB_SW_INTERFACES_t*> + (PsiBridgeAddr); + + // Read back PSIHBBAR + TRACUCOMP(g_trac_tce,"UtilTceMgr::initTceInHdw: Read Back psihbbar = 0x%.16llX", l_psihb_ptr->psihbbar); + + + // Set TAR - TCE Address Register + // Put the TCE Table Starting Physical Address and set up the + // system for max of 512K entries + l_tar.WholeTAR=0; + + // Since iv_tceTablePhysAddr already checked for 4MB alignment in + // createTceTable() we can copy it directly in here + l_tar.WholeTAR = iv_tceTablePhysAddr; + l_tar.tceEntries = TAR_TCE_ENTRIES_512K; + + TRACFCOMP(g_trac_tce,"UtilTceMgr::initTceInHdw: iv_tceTablePhysAddr = 0x%.16llX, l_psihb_ptr=0x%.16llX, TAR=0x%.16llX",iv_tceTablePhysAddr, l_psihb_ptr, l_tar.WholeTAR); + + l_psihb_ptr->tceaddr = l_tar.WholeTAR; + + eieio(); + + TRACUCOMP(g_trac_tce,"UtilTceMgr::initTceInHdw: Read Back tceaddr = 0x%.16llX", l_psihb_ptr->tceaddr); + + // Turn on TCE enable PSI Host Bridge Secure Register + l_psihb_ptr->phbsecure = PHBSECURE_TCE_ENABLE; + + eieio(); + + TRACUCOMP(g_trac_tce,"UtilTceMgr::initTceInHdw: Read Back phbsecure = 0x%.16llX", l_psihb_ptr->phbsecure); + + // Unmap the PSI Host Bridge + errl = unmapPsiHostBridge(PsiBridgeAddr); + if (errl) + { + TRACFCOMP(g_trac_tce,"UtilTceMgr::initTceInHdw: call to unmapPsiHostBridge failed with rc=0x%X, plid=0x%X. Committing Log, but continuing the loop", ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + errlCommit( errl, UTIL_COMP_ID ); + continue; + } + TRACUCOMP(g_trac_tce,"UtilTceMgr::initTceInHdw: After unmap: Psi Bridge Addr = 0x%.16llX huid = 0x%.8X", PsiBridgeAddr, TARGETING::get_huid(l_pTarget)); + + } + + }while(0); + + // If succsesfull set init to true + if ((errl == nullptr) && + (iv_isTceHwInitDone == false)) + { + iv_isTceHwInitDone = true; + + // Successfully initialized the TCE table and hardware. + TRACUCOMP(g_trac_tce, "UtilTceMgr::initTceInHdw: TCE initialized and setup"); + } + + TRACFCOMP(g_trac_tce, EXIT_MRK"UtilTceMgr::initTceInHdw: iv_isTceHwInitDone=%d", iv_isTceHwInitDone); + + return errl; +} + + +/************************************************************************/ +// +// NAME: allocateTces +// Responsible for allocating TCE Entries +// +/************************************************************************/ +errlHndl_t UtilTceMgr::allocateTces(const uint64_t i_startingAddress, + const size_t i_size) +{ + errlHndl_t errl = nullptr; + uint32_t numTcesNeeded = 0; + + TceEntry_t *tablePtr = nullptr; + + TRACFCOMP(g_trac_tce,ENTER_MRK"UtilTceMgr::allocateTces: start for addr = 0x%.16llX and size = 0x%X", i_startingAddress, i_size); + + do + { + // Assert if i_size is not greater than zero + assert(i_size > 0, "UtilTceMgr::allocateTces: i_size = %d, not greater than zero", i_size); + + // Expecting a page-aligned starting address + if (i_startingAddress % PAGESIZE) + { + TRACFCOMP(g_trac_tce,ERR_MRK"UtilTceMgr::allocateTces: ERROR-Address 0x%.16llX not page aligned", i_startingAddress); + + /*@ + * @errortype + * @moduleid Util::UTIL_TCE_ALLOCATE + * @reasoncode Util::UTIL_TCE_ADDR_NOT_ALIGNED + * @userdata1 Address to start TCE + * @userdata2 Size of the address space trying to get TCEs + * for. + * @devdesc The Physical Address for the TCE entry is not + * page aligned. + * @custdesc A problem occurred during the IPL of the system + */ + errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + Util::UTIL_TCE_ALLOCATE, + Util::UTIL_TCE_ADDR_NOT_ALIGNED, + i_startingAddress, + i_size, + true /*Add HB SW Callout*/); + + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + break; + } + + // Calculate the number of TCE entries needed - rounding up + numTcesNeeded = ALIGN_PAGE(i_size)/PAGESIZE; + + // If more than the number of TCEs available error out + if (numTcesNeeded > iv_tceEntryCount) + { + TRACFCOMP(g_trac_tce,ERR_MRK"UtilTceMgr::allocateTces: ERROR - Too many entries (0x%X) requested (>0x%X) (i_size=0x%X)", numTcesNeeded, iv_tceEntryCount, i_size); + + /*@ + * @errortype + * @moduleid Util::UTIL_TCE_ALLOCATE + * @reasoncode Util::UTIL_TCE_INVALID_SIZE + * @userdata1[0:31] Number of TCEs Needed + * @userdate1[32:64] Maximum Number of Tce Entries + * @userdata2 Size of the address space trying to get TCEs + * @devdesc The size requested is too large for the table + * @custdesc A problem occurred during the IPL of the system + */ + errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + Util::UTIL_TCE_ALLOCATE, + Util::UTIL_TCE_INVALID_SIZE, + TWO_UINT32_TO_UINT64( + numTcesNeeded, + iv_tceEntryCount), + i_size, + true /*Add HB SW Callout*/); + + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + break; + } + + // @TODO RTC 168745 additional error checking when iv_allocatedAddrs + // will be updated to keep track of size, too + + // Check to see if we've already allocated TCEs associated with + // this starting address + std::map<uint64_t, uint32_t>::iterator map_itr + = iv_allocatedAddrs.find(i_startingAddress); + if(map_itr != iv_allocatedAddrs.end()) + { + // This starting address has already had TCEs allocated for it + TRACFCOMP(g_trac_tce,"UtilTceMgr::allocateTces: ERROR - This starting address 0x%.16llX already has TCEs allocated (pos=0x%X)", i_startingAddress, map_itr->second); + + /*@ + * @errortype + * @moduleid Util::UTIL_TCE_ALLOCATE + * @reasoncode Util::UTIL_TCE_PREVIOUSLY_ALLOCATED + * @userdata1 Starting Address + * @userdata2 Starting TCE position in TCE Table + * @devdesc The starting address was previously allocated + * @custdesc A problem occurred during the IPL of the system + */ + errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + Util::UTIL_TCE_ALLOCATE, + Util::UTIL_TCE_PREVIOUSLY_ALLOCATED, + i_startingAddress, + map_itr->second, + true /*Add HB SW Callout*/); + + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + break; + } + // Will set map_itr->second with TCE table position later + + // Check to see if createTceTable ran before allocate. If not we + // need to create the table and make sure it is mapped. + // If we are in multi-node we would run create on only 1 node and + // other nodes could use that table + if (!iv_isTceTableInitDone) + { + // createTceTable has not run + TRACFCOMP(g_trac_tce,"UtilTceMgr::allocateTces: createTceTable has not run so call createTceTable() here."); + + errl = createTceTable(); + + if (errl) + { + TRACFCOMP(g_trac_tce,"UtilTceMgr::allocateTces: createTceTable() failed with rc=0x%X",ERRL_GETRC_SAFE(errl)); + break; + } + } + + // Check to see if HW has been initialized to use the TCEs + if (!iv_isTceHwInitDone) + { + // TceInit did not run before allocate was called so call it here + TRACFCOMP(g_trac_tce,"UtilTceMgr::allocateTces: initTceInHdw has not run yet: call it now"); + + errl = initTceInHdw(); + + if (errl) + { + TRACFCOMP(g_trac_tce,"UtilTceMgr::allocateTces: initTceInHdw() failed with rc=0x%X",ERRL_GETRC_SAFE(errl)); + break; + } + } + + tablePtr = reinterpret_cast<TceEntry_t*>(iv_tceTableVaAddr); + + // Find a first consecutive group of TCEs requested + uint32_t startingIndex = 0; + bool found = false; + + // Start at the beginning and search for the first empty entry + for (uint32_t tceIndex = 0; + tceIndex < iv_tceEntryCount; + ++tceIndex) + { + // Look for no-write AND no-read access for the entry to be empty + if (tablePtr[tceIndex].readAccess == 0 && + tablePtr[tceIndex].writeAccess == 0) + { + uint32_t availIndex = 0; + + // if not enough space avail. + if (numTcesNeeded+tceIndex > iv_tceEntryCount) + { + break; + } + for (uint32_t IndexInRow = tceIndex; + IndexInRow < numTcesNeeded + tceIndex; + IndexInRow++) + { + // If the entry has no read or write access then the + // entry is available + if (tablePtr[IndexInRow].readAccess == 0 && + tablePtr[IndexInRow].writeAccess == 0) + { + // 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 entries + 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. + } + } + + TRACUCOMP(g_trac_tce,"UtilTceMgr::allocateTces: found=%d, startingIndex=0x%X, numTcesNeeded=0x%X", found, startingIndex, numTcesNeeded); + + if (found) + { + // Do a for loop here to loop through the number of TCE entries + // and set the valid bits. The real page number gets incremented + // by 1 for each entry + for ( uint32_t i = 0, index=startingIndex; + i < numTcesNeeded; + ++i, ++index ) + { + tablePtr[index].realPageNumber = (i_startingAddress + + (i*PAGESIZE))/PAGESIZE; + tablePtr[index].writeAccess = 1; + tablePtr[index].readAccess = 1; + + TRACDCOMP(g_trac_tce,INFO_MRK"UtilTceMgr::allocateTces: TCE Entry/Token[%d] (hex) = %llX", index, tablePtr[index]); + } + + iv_allocatedAddrs[i_startingAddress] = startingIndex; + + TRACFCOMP(g_trac_tce,"UtilTceMgr::allocateTces: SUCCESSFUL: addr = 0x%.16llX, size = 0x%llX, starting entry=0x%X",i_startingAddress, i_size, startingIndex); + } + else // not found means not enough space for request + { + TRACFCOMP(g_trac_tce,"UtilTceMgr::allocateTces: ERROR -Not enough free entries for this request: addr=0x%.16llX, size=0x%llX, startingIndex=0x%X, numTcesNeeded=0x%X", i_startingAddress, i_size, startingIndex, numTcesNeeded); + + /*@ + * @errortype + * @moduleid Util::UTIL_TCE_ALLOCATE + * @reasoncode Util::UTIL_TCE_NOT_ENOUGH_FREE_ENTRIES + * @userdata1[0:31] Number of TCEs Needed + * @userdate1[32:64] Starting Index in TCE Table + * @userdata2 Size of address space TCEs are tying to map to + * @devdesc Requested size is too large to fit into TCE Table + * @custdesc A problem occurred during the IPL of the system + */ + errl = new ERRORLOG::ErrlEntry( + ERRORLOG::ERRL_SEV_UNRECOVERABLE, + Util::UTIL_TCE_ALLOCATE, + Util::UTIL_TCE_NOT_ENOUGH_FREE_ENTRIES, + TWO_UINT32_TO_UINT64( + numTcesNeeded, + startingIndex), + i_size, + true /*Add HB SW Callout*/); + + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + break; + } + }while(0); + + TRACFCOMP(g_trac_tce, EXIT_MRK"UtilTceMgr::allocateTces: END: addr = 0x%.16llX and size = 0x%X, numTcesNeeded=0x%X", i_startingAddress, i_size, numTcesNeeded); + printIvMap(); //Debug + + return errl; +} + + +/*************************************************************************/ +// +// NAME: deallocateTces +// Responsible for deallocating TCE Entries +// +/*************************************************************************/ +errlHndl_t UtilTceMgr::deallocateTces(const uint64_t i_startingAddress, + const size_t i_size) +{ + + errlHndl_t errl = nullptr; + bool isContiguous = true; + uint32_t startingIndex = 0; + + TceEntry_t *tablePtr = nullptr; + + TRACFCOMP(g_trac_tce,ENTER_MRK"UtilTceMgr::deallocateTces: Address = 0x%.16llX for size = 0x%X",i_startingAddress, i_size); + + do + { + + // Assert if i_size is not greater than zero + assert(i_size > 0, "UtilTceMgr::deallocateTces: i_size = %d, not greater than zero", i_size); + + // Expecting a page-aligned starting address + if (i_startingAddress % PAGESIZE) + { + TRACFCOMP(g_trac_tce,ERR_MRK"UtilTceMgr::deallocateTces: ERROR-Address 0x%.16llX not page aligned", i_startingAddress); + + /*@ + * @errortype + * @moduleid Util::UTIL_TCE_DEALLOCATE + * @reasoncode Util::UTIL_TCE_ADDR_NOT_ALIGNED + * @userdata1 Address to start TCE + * @userdata2 Size of the address space trying to get TCEs + * for. + * @devdesc The Physical Address for the TCE entry is not + * page aligned. + * @custdesc A problem occurred during the IPL of the system + */ + errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + Util::UTIL_TCE_DEALLOCATE, + Util::UTIL_TCE_ADDR_NOT_ALIGNED, + i_startingAddress, + i_size, + true /*Add HB SW Callout*/); + + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + break; + } + + + // Get number of TCEs needed - rounding up + uint32_t numTcesNeeded = ALIGN_PAGE(i_size)/PAGESIZE; + + std::map<uint64_t, uint32_t>::iterator map_itr + = iv_allocatedAddrs.find(i_startingAddress); + if( map_itr == iv_allocatedAddrs.end() ) + { + // Can't find this starting address. Trace that nothing happens, + // but do not create an error log + TRACFCOMP(g_trac_tce,INFO_MRK"UtilTceMgr::deallocateTces: Can't find match of Starting Address = 0x%.16llX (size = 0x%X)",i_startingAddress, i_size); + break; + } + else + { + startingIndex = map_itr->second; + } + TRACUCOMP(g_trac_tce,"UtilTceMgr::deallocateTces: numTcesNeeded=0x%X, startingAddress = 0x%X", numTcesNeeded, i_startingAddress); + + // @TODO RTC 168745 additional error checking when iv_allocatedAddrs + // will be updated to keep track of size, too + + // startingIndex is larger than the max number of indexes avail + // --OR-- startingIndex and the number of TCEs needed exceeds the + // number of TCEs in the Table + if (startingIndex > iv_tceEntryCount || + startingIndex+numTcesNeeded > iv_tceEntryCount) + { + TRACFCOMP(g_trac_tce,ERR_MRK"UtilTceMgr::deallocateTces: Invalid startingAddress=0x%X and/or numTcesNeeded=0x%X for table with iv_tceEntryCount=0x%X, No deallocate.", i_startingAddress, numTcesNeeded, iv_tceEntryCount); + + /*@ + * @errortype + * @moduleid Util::UTIL_TCE_DEALLOCATE + * @reasoncode Util::UTIL_TCE_INVALID_SIZE + * @userdata1[0:31] starting index + * @userdata1[32:63] number of TCEs needed for this request + * @userdata2 Number of Entries Current TCE Table Supports + * @devdesc The size requested is too large based on the + * startingAddress the space avilable in the table + * @custdesc A problem occurred during the IPL of the system + */ + errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + Util::UTIL_TCE_DEALLOCATE, + Util::UTIL_TCE_INVALID_SIZE, + TWO_UINT32_TO_UINT64( + startingIndex, + numTcesNeeded), + iv_tceEntryCount, + true /*Add HB SW Callout*/); + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + + errlCommit(errl,UTIL_COMP_ID); + + break; + } + + // Currently do not check for valid entries.. Just clear as + // requested. + uint64_t previousAddress = 0; + + tablePtr = reinterpret_cast<TceEntry_t*>(iv_tceTableVaAddr); + + for (uint32_t tceIndex = startingIndex; + tceIndex < (startingIndex + numTcesNeeded); + tceIndex++) + { + + // check that the address space is contiguous + if ((tceIndex != startingIndex) && + ((tablePtr[tceIndex].realPageNumber - + previousAddress) != 1)) + { + isContiguous = false; + TRACUCOMP(g_trac_tce,INFO_MRK"UtilTceMgr::deallocateTces: isContiguous set to false (%d) for tablePtr[tceIndex=0x%X]=0x%.16llX, previousAddress_RPN=0x%X", isContiguous, tceIndex, tablePtr[tceIndex].WholeTceEntry, previousAddress); + } + + // Save off real address of page pointed to be this TCE for + // isContiguous check on next interation + previousAddress = tablePtr[tceIndex].realPageNumber; + + // Clear out the TCE entry to 0 + tablePtr[tceIndex].WholeTceEntry = 0; + } + + // Remove the entry from iv_allocatedAddrs even if 'isContiguous' issue + iv_allocatedAddrs.erase(i_startingAddress); + + if (!isContiguous) + { + // We know the range to delete is not contingous. The address and + // size inputs crossesd other allocates. + // Error log created to indicate this but will clear number of + // entries requested by caller + TRACFCOMP(g_trac_tce,"UtilTceMgr::deallocateTces: ERROR - request was not contiguous TCE entries"); + + /*@ + * @errortype + * @moduleid Util::UTIL_TCE_DEALLOCATE + * @reasoncode Util::UTIL_TCE_ENTRY_NOT_CONTIGUOUS + * @userdata1 Starting address of the TCEs to be deallocated + * @userdata2 Size of the address space to be deallocated + * @devdesc The deallocate went across TCE Allocate space. + * @custdesc A problem occurred during the IPL of the system + */ + errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_PREDICTIVE, + Util::UTIL_TCE_DEALLOCATE, + Util::UTIL_TCE_ENTRY_NOT_CONTIGUOUS, + i_startingAddress, + i_size, + true /*Add HB SW Callout*/); + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + + TRACFCOMP(g_trac_tce,"UtilTceMgr::deallocateTces: not-contiuguos ERROR created (rc=0x%X) and committed", ERRL_GETRC_SAFE(errl)); + errlCommit(errl,UTIL_COMP_ID); + break; + } + + }while(0); + + TRACFCOMP(g_trac_tce,"UtilTceMgr::deallocateTces: COMPLETE for Addr = 0x%.16llX for size = 0x%X, errl=0x%X",i_startingAddress, i_size, ERRL_GETRC_SAFE(errl)); + printIvMap(); //Debug + + return errl; +} + + +/**************************************************************************/ +// +// NAME: disableTce +// Deallocate any TCE entries and disable HW settings +// +/**************************************************************************/ +errlHndl_t UtilTceMgr::disableTces(void) +{ + errlHndl_t errl = nullptr; + int64_t rc = 0; + + TRACUCOMP(g_trac_tce,ENTER_MRK"UtilTceMgr::disableTces: iv_isTceHwInitDone=%d, iv_tceTableVaAddr=0x%.16llX iv_isTceTableInitDone=%d", iv_isTceHwInitDone, iv_tceTableVaAddr, iv_isTceTableInitDone ); + + do { + + // If the HW was initialized to use TCEs then disable those settings + // it needs to be released here + if (iv_isTceHwInitDone) + { + // Loop through the processors and clear the TCE-related registers + // in the PSI Host Bridge + TARGETING::TargetHandleList l_cpuTargetList; + getAllChips(l_cpuTargetList, TARGETING::TYPE_PROC); + + for ( auto l_pTarget : l_cpuTargetList ) + { + void * PsiBridgeAddr = nullptr; + INTR::PSIHB_SW_INTERFACES_t * l_psihb_ptr = nullptr; + + // MMIO Map the PSI Host Bridge + errl = mapPsiHostBridge(l_pTarget, PsiBridgeAddr); + if (errl) + { + TRACFCOMP(g_trac_tce,"UtilTceMgr::disableTces: call to mapPsiHostBridge failed with rc=0x%X, plid=0x%X. Committing Log, but continuing the loop", ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + errlCommit( errl, UTIL_COMP_ID ); + continue; + } + + TRACUCOMP(g_trac_tce,"UtilTceMgr::disableTces: Psi Bridge Addr = 0x%.16llX huid = 0x%.8X", PsiBridgeAddr, TARGETING::get_huid(l_pTarget)); + + l_psihb_ptr = reinterpret_cast<INTR::PSIHB_SW_INTERFACES_t*> + (PsiBridgeAddr); + + // Read back PSIHBBAR + TRACUCOMP(g_trac_tce,"UtilTceMgr::disableTces: Read Back psihbbar = 0x%.16llX", l_psihb_ptr->psihbbar); + + // Turn off TCE enable PSI Host Bridge Secure Register + l_psihb_ptr->phbsecure = 0x0; + + eieio(); + + TRACUCOMP(g_trac_tce,"UtilTceMgr::disableTces: Read Back phbsecure = 0x%.16llX", l_psihb_ptr->phbsecure); + + // Clear TAR - TCE Address Register + l_psihb_ptr->tceaddr = 0x0; + + eieio(); + + TRACUCOMP(g_trac_tce,"UtilTceMgr::disableTces: Read Back tceaddr = 0x%.16llX", l_psihb_ptr->tceaddr); + + // Unmap the PSI Host Bridge + errl = unmapPsiHostBridge(PsiBridgeAddr); + if (errl) + { + TRACFCOMP(g_trac_tce,"UtilTceMgr::disableTces: call to unmapPsiHostBridge failed with rc=0x%X, plid=0x%X. Committing Log, but continuing the loop", ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + errlCommit( errl, UTIL_COMP_ID ); + continue; + } + TRACUCOMP(g_trac_tce,"UtilTceMgr::disableTces: After unmap: Psi Bridge Addr = 0x%.16llX huid = 0x%.8X", PsiBridgeAddr, TARGETING::get_huid(l_pTarget)); + + } + + // Clear the class variable + iv_isTceHwInitDone=false; + + } + else + { + TRACUCOMP(g_trac_tce,"UtilTceMgr::disableTces: No Need To Uninitialize HW: iv_isTceHwInitDone=%d", iv_isTceHwInitDone); + } + + // Cleanup TCE Table In Memory + if ( (iv_tceTableVaAddr!= 0) && (iv_isTceTableInitDone==true)) + { + + // Clear TCE Table + memset(reinterpret_cast<void*>(iv_tceTableVaAddr), 0, iv_tceTableSize); + + // Unmap TCE Table In Memory + rc = mm_block_unmap(reinterpret_cast<void*>(iv_tceTableVaAddr)); + + if ( rc ) + { + // Got a bad rc from mm_block_unmap + TRACFCOMP(g_trac_tce, "UtilTceMgr::disableTces: mm_unmap_block failed: rc = 0x%.16llX, iv_tceTableVaAddr=0x%.16llX iv_tceTablePhysAddr=0x%X", rc, iv_tceTableVaAddr, iv_tceTablePhysAddr, rc); + + /*@ + * @errortype + * @moduleid Util::UTIL_TCE_DISABLE_TCES + * @reasoncode Util::UTIL_TCE_BLOCK_UNMAP_FAIL + * @userdata1 Starting virtual address of pages to be removed + * @userdata2 Return Code from mm_block_unmap + * @devdesc mm_block_unmap failed for TCE Table + * @custdesc A problem occurred during the IPL of the system + */ + errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + Util::UTIL_TCE_DISABLE_TCES, + Util::UTIL_TCE_BLOCK_UNMAP_FAIL, + iv_tceTableVaAddr, + rc, + true /*Add HB SW Callout*/); + + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + break; + } + + // Clear the class variable + iv_isTceTableInitDone=false; + } + else + { + TRACFCOMP(g_trac_tce,"UtilTceMgr::disableTces: iv_tceTableVaAddr == NULL (0x%.16llX) - No Cleanup of TCE Table", iv_tceTableVaAddr); + } + + // Clear allocated addresses map + iv_allocatedAddrs.clear(); + + }while(0); + + TRACUCOMP(g_trac_tce,EXIT_MRK"UtilTceMgr::disableTces"); + printIvMap(); //Debug + + return errl; +} + + +/**************************************************************************/ +// +// NAME: ~UtilTceMgr +// Destructor +// +/**************************************************************************/ +UtilTceMgr::~UtilTceMgr() +{ + errlHndl_t errl = nullptr; + + TRACUCOMP(g_trac_tce,"UtilTceMgr::~UtilTceMgr"); + + // Call disableTce in case it hasn't already been called + errl = disableTces(); + + if (errl) + { + TRACFCOMP(g_trac_tce,"UtilTceMgr::~UtilTceMgr: disableTces Failed rc=0x%X. Committing plid=0x%X", ERRL_GETRC_SAFE(errl), ERRL_GETPLID_SAFE(errl)); + errlCommit( errl, UTIL_COMP_ID ); + } + + iv_allocatedAddrs.clear(); +} + +// Debug for printing out iv_allocatedAddrs map +void UtilTceMgr::printIvMap(void) const +{ + TRACUCOMP(g_trac_tce,"UtilTceMgr::printIvMap: size=%d", iv_allocatedAddrs.size()); + + for ( auto map_itr : iv_allocatedAddrs ) + { + TRACUCOMP(g_trac_tce,"UtilTceMgr: printIvMap: addr=0x%.16llX, pos=0x%X", map_itr.first, map_itr.second); + } + +} + + +/**************************************************************************/ +// +// NAME: mapPsiHostBridge: +// Helper function to Memory Map PSI Host Bridge +// +/**************************************************************************/ +errlHndl_t UtilTceMgr::mapPsiHostBridge(const TARGETING::Target * i_tgt, + void *& o_psihb_ptr) const +{ + errlHndl_t errl = nullptr; + void * l_ptr = nullptr; + o_psihb_ptr = nullptr; + + // Assert if i_tgt is NULL or not a Processor + assert((i_tgt != nullptr) && + (i_tgt->getAttr<TARGETING::ATTR_TYPE>() == TARGETING::TYPE_PROC ), + "UtilTceMgr::mapPsiHostBridge: i_tgt=0x%X either NULL or !TYPE_PROC", + TARGETING::get_huid(i_tgt)); + + uint64_t PsiBridgeAddr = + i_tgt->getAttr<TARGETING::ATTR_PSI_BRIDGE_BASE_ADDR>(); + + TRACUCOMP(g_trac_tce,ENTER_MRK"UtilTceMgr::mapPsiHostBridge:Psi Bridge Addr = 0x%.16llX huid = 0x%.8X", PsiBridgeAddr, TARGETING::get_huid(i_tgt)); + + // Assert if the PSI_BRIDEG_BASE_ADDR is zero or not page aligned + assert((PsiBridgeAddr != 0) && + ((PsiBridgeAddr - ALIGN_PAGE_DOWN(PsiBridgeAddr)) == 0), + "PsiBridgeAddr (0x%.16llX) is ZERO or not Page Aligned", + PsiBridgeAddr); + + // Map the device for the PSI_BRIDGE_ADDR + l_ptr = mmio_dev_map(reinterpret_cast<void*>(PsiBridgeAddr), PAGESIZE); + + if (l_ptr == nullptr) + { + // Got a bad rc from device Map + TRACFCOMP(g_trac_tce, "UtilTceMgr::mapPsiHostBtidge: Device map error."); + + /*@ + * @errortype + * @moduleid Util::UTIL_TCE_MAP_PSIHB + * @reasoncode Util::UTIL_TCE_DEV_MAP_FAIL + * @userdata1 Address to be mapped PsiBridgeAddr + * @userdata2 Target Unit Id + * @devdesc PSI Bridge device Map failed + * @custdesc A problem occurred during the IPL of the + * system + */ + errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + Util::UTIL_TCE_MAP_PSIHB, + Util::UTIL_TCE_DEV_MAP_FAIL, + PsiBridgeAddr, + TARGETING::get_huid(i_tgt), + true /*Add HB SW Callout*/); + + errl->addHwCallout( i_tgt, + HWAS::SRCI_PRIORITY_HIGH, + HWAS::DELAYED_DECONFIG, + HWAS::GARD_NULL ); + + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + } + o_psihb_ptr = l_ptr; + + TRACUCOMP(g_trac_tce,EXIT_MRK"UtilTceMgr::mapPsiHostBridge: o_psihb_ptr=0x%.16llX, Psi Bridge Addr = 0x%.16llX, huid = 0x%.8X", o_psihb_ptr, PsiBridgeAddr, TARGETING::get_huid(i_tgt)); + + return errl; +} + + +/**************************************************************************/ +// +// NAME: unmapPsiHostBridge: +// Helper function to Unmap PSI Host Bridge from Memory +// +/**************************************************************************/ +errlHndl_t UtilTceMgr::unmapPsiHostBridge(void *& io_psihb_ptr) const +{ + errlHndl_t errl = nullptr; + int64_t rc = 0; + + TRACUCOMP(g_trac_tce,ENTER_MRK"UtilTceMgr::unmapPsiHostBridge: " + "io_psihb_ptr = %p", io_psihb_ptr); + + // unmap the device.. + rc = mmio_dev_unmap(io_psihb_ptr); + + if (rc != 0) + { + // Got a bad rc from device unmap + TRACFCOMP(g_trac_tce, "UtilTceMgr::unmapPsiHostBridge: device unmap " + "error: rc=0x%X", rc); + + /*@ + * @errortype + * @moduleid Util::UTIL_TCE_UNMAP_PSIHB + * @reasoncode Util::UTIL_TCE_DEV_UNMAP_FAIL + * @userdata1 Address to be unmapped + * @userdata2 Return Code of mmio_dev_unmap + * @devdesc PSI Bridge device Map failed + * @custdesc A problem occurred during the IPL of the + * system + */ + errl = new ERRORLOG::ErrlEntry(ERRORLOG::ERRL_SEV_UNRECOVERABLE, + Util::UTIL_TCE_UNMAP_PSIHB, + Util::UTIL_TCE_DEV_UNMAP_FAIL, + reinterpret_cast<uint64_t>(io_psihb_ptr), + rc, + true /*Add HB SW Callout*/); + + errl->collectTrace(UTILTCE_TRACE_NAME,KILOBYTE); + } + else + { + io_psihb_ptr = nullptr; + TRACUCOMP(g_trac_tce,EXIT_MRK"UtilTceMgr::unmapPsiHostBridge Successful"); + } + + return errl; +} + +}; // namespace TCE + +#endif diff --git a/src/usr/util/utiltcemgr.H b/src/usr/util/utiltcemgr.H new file mode 100644 index 000000000..3f8d2b95c --- /dev/null +++ b/src/usr/util/utiltcemgr.H @@ -0,0 +1,290 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/usr/util/utiltcemgr.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2013,2017 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ +#ifndef __UTILTCEMGR_H +#define __UTILTCEMGR_H + +#include <stdint.h> +#include <builtins.h> +#include <errl/errlentry.H> +#include <devicefw/userif.H> +#include <intr/interrupt.H> +#include <map> + +// Forward declarations +class TCETest; + +namespace TCE +{ + +struct TceEntry_t +{ + // Derived from "15.9.6 TCE - Translation Control Entry" of the + // P9 Pervasive Workbook + union + { + uint64_t WholeTceEntry; + struct { + uint64_t reserved_0 :8; // first 8 bits reserved + uint64_t realPageNumber :44; // real page number + uint64_t reserved_1 :10; // reserved bits + uint64_t writeAccess :1; // Write access allowed + uint64_t readAccess :1; // Read access allowed + }; + + }; + + // Constructor to default to zero + TceEntry_t() : + WholeTceEntry(0x0) {}; + +}; + +struct TarTceAddrRegister_t +{ + // Derived from "15.9.6 TCE - Translation Control Entry" of the + // P9 Pervasive Workbook + union + { + uint64_t WholeTAR; + struct { + uint64_t reserved_0 :8; // first 8 bits reserved + uint64_t tceTableStartAddr :34; // real page number + uint64_t reserved_1 :6; // reserved since 512k entries + uint64_t reserved_2 :13; // reserved + uint64_t tceEntries :3; // TCE Entries + }; + }; + + // Constructor to default to zero + TarTceAddrRegister_t() : + WholeTAR(0x0) {}; + +}; + + +/** @class UtilTceMgr + * @brief Responsible for managing the TCE entries + * + */ +class UtilTceMgr +{ + + private: + /** Indicator of TCEs being intialized */ + bool iv_isTceHwInitDone; + + /** Indicator of TCE Table being allocated and initialized in memory */ + bool iv_isTceTableInitDone; + + /** Virtual Address of the Mapped TCE Table */ + uint64_t iv_tceTableVaAddr; + + /** Physical Address of the TCE Table */ + uint64_t iv_tceTablePhysAddr; + + /** Number of TCE entries - via size */ + size_t iv_tceEntryCount; + + /** size of the Tce Table */ + size_t iv_tceTableSize; + + /* Cache of starting addresses of allocated TCEs and their + * starting entry in the TCE Table + * Indexed by starting address, returns position of first entry + * in the TCE table associated with this starting address + * @TODO RTC 168745 update this to a vector of structs that keeps track of + * starting address, first entry, and size of memory covered for + * better error handling + */ + std::map<uint64_t, uint32_t> iv_allocatedAddrs; + + /* For Debug purposes */ + void printIvMap() const; + + /** Max TCE Entries and Size for the TCE Table */ + enum + { + MAX_NUM_TCE_TABLE_ENTRIES = 0x080000, // 512k entries - HW Max + MAX_TCE_TABLE_SIZE = 0x400000, // 512k * 8 bytes/entry + }; + + /** Values related to PSIHB_SW_INTERFACES_t registers */ + enum + { + TAR_TCE_ENTRIES_512K = 0b100, // TAR bits 61:63=0b100 for 512K entries + PHBSECURE_TCE_ENABLE = 0x2000000000000000, + }; + + /** + * @brief Responsible for initalizing the TCE Table and mapping the + * TCE Table into memory + * + * @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 Helper function to Memory Map PSI Host Bridge + * + * @param[in] i_tgt Pointer to Processor Target that is associated + * with a specific PSI Host Bridge Memory Map. + * Assert if NULL or not a Processor Target + * + * @param[out] o_psihb_ptr If successful, pointer to memory mapped + * location of PSI Host Bridge; + * otherwise, NULL + * + * @return errlHndl_t - Return error log if unsuccessful + * + */ + errlHndl_t mapPsiHostBridge(const TARGETING::Target* i_tgt, + void *& o_psihb_ptr) const; + + + /** + * @brief Helper function to Unmap PSI Host Bridge from Memory + * + * @param[in] i_psihb_ptr Pointer to memory mapped location of + * PSI Host Bridge + * + * @return errlHndl_t - Return error log if unsuccessful + * + */ + errlHndl_t unmapPsiHostBridge(void *& i_psihb_ptr) const; + + + /* let the testcase poke around */ + friend class ::TCETest; + + + public: + /** + * @brief Constructor. Initializes instance variables. + * @param[in/default] i_tableAddr - Starting physical address of the TCE + * Table. Default address is TCE_TABLE_ADDR. + * Address must be aligned on a 4MB boundary or will fail. + * @param[in/default] i_tableSize - Size of the TCE table. Default value + * is TCE_TABLE_SIZE + * + * @note TCE_TABLE_ADDR and TCE_TABLE_SIZE are defined in vmmconst.h + */ + UtilTceMgr(uint64_t i_tableAddr = TCE_TABLE_ADDR, + size_t i_tableSize = TCE_TABLE_SIZE); + + /** + * Destructor. + */ + ~UtilTceMgr(); + + /** + * Delete Copy Constructor + */ + UtilTceMgr(const UtilTceMgr&) = delete; + + /** + * Delete Copy Assignment + */ + UtilTceMgr& operator= (const UtilTceMgr&) = delete; + + /** + * Delete Move Constructor + */ + UtilTceMgr (UtilTceMgr&&) = delete; + + /** + * Delete Move Assignment + */ + UtilTceMgr& operator = (UtilTceMgr&&) = delete; + + + /** + * @brief Responsible for allocating TCEs + * + * @param[in] i_startingAddress - Starting address that the allocated TCEs + * will map to + * Needs to be page-aligned or will fail + * @param[in] i_size - Size of the address space that TCEs map to + * Size must be less than (512K * PAGESIZE) or will fail + * Assert if not greater than zero + * + * Note: First time this is called will cause TCE table to be created and + * the Processors to be setup to point at the TCE table + * + * @return errl - Return Error Handle if failed. + * + */ + errlHndl_t allocateTces(uint64_t i_startingAddress, + size_t i_size); + + /** + * @brief Responsible for deallocating TCEs + * + * @param[in] i_startingAddress Starting Address that the TCEs that + * are to be deallocated map to + * Address needs to be page-aligned. + * @param[in] i_size - Size of address space that the TCEs that are to + * be deallocated map to + * Size must be less than (512K * PAGESIZE) or will fail + * Assert if not greater than zero + * + * @return errl - Return Error Handle if fatal failure occurred. + * + */ + errlHndl_t deallocateTces(uint64_t i_startingAddress, + size_t i_size); + + /** + * @brief Responsible for disabling TCEs on the system, including + * clearing the TCE table and disabling Processor settings + * + * @return errl - Return Error Handle if fatal failure occurred. + * + */ + errlHndl_t disableTces(void); + +}; // class UtilTceMgr + + /** + * @brief Returns a copy of the UtilTceMgr Singleton + * + * @return Returns a copy of Singleton<UtilTceMgr>::instance() + */ + UtilTceMgr& getTceManager(void); + +}; // namespace + +#endif + |