summaryrefslogtreecommitdiffstats
path: root/src/usr/util
diff options
context:
space:
mode:
authorMike Baiocchi <mbaiocch@us.ibm.com>2016-11-04 11:30:17 -0500
committerWilliam G. Hoffa <wghoffa@us.ibm.com>2017-03-08 11:06:34 -0500
commitc3d233bbaf7a2f274147d16edbc080bae0ffd714 (patch)
tree8058bc8e764135eecc21cdcd1177814dd4e180c8 /src/usr/util
parent1301e43641f7d3f315a0abc8112fa88927c9fa9a (diff)
downloadtalos-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/util')
-rw-r--r--src/usr/util/makefile3
-rw-r--r--src/usr/util/test/testtcemgr.H363
-rw-r--r--src/usr/util/utiltcemgr.C1276
-rw-r--r--src/usr/util/utiltcemgr.H290
4 files changed, 1931 insertions, 1 deletions
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
+
OpenPOWER on IntegriCloud