diff options
author | Brad Bishop <bradleyb@us.ibm.com> | 2012-07-11 21:21:17 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2012-09-04 10:35:26 -0500 |
commit | 0c1b5c905ee077e232924f7541df73f4d2e6c862 (patch) | |
tree | d961fa48df8fa5b3f9229b3a8f063cd9d444bd01 | |
parent | bc96bf7d92d34132310545037845d8f93fa4d953 (diff) | |
download | talos-hostboot-0c1b5c905ee077e232924f7541df73f4d2e6c862.tar.gz talos-hostboot-0c1b5c905ee077e232924f7541df73f4d2e6c862.zip |
Attention handler support for memory attentions.
RTC: 41423
Change-Id: Iadf1c8062c740f20be78306a7da2958347a11222
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/1363
Reviewed-by: Zane Shelley <zshelle@us.ibm.com>
Tested-by: Jenkins Server
Reviewed-by: LARINA M. DSOUZA <larsouza@in.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r-- | src/usr/diag/attn/attn.C | 11 | ||||
-rw-r--r-- | src/usr/diag/attn/attnfwd.H | 1 | ||||
-rw-r--r-- | src/usr/diag/attn/attnmem.C | 265 | ||||
-rw-r--r-- | src/usr/diag/attn/attnmem.H | 117 | ||||
-rw-r--r-- | src/usr/diag/attn/attnsvc.H | 1 | ||||
-rw-r--r-- | src/usr/diag/attn/makefile | 2 | ||||
-rw-r--r-- | src/usr/diag/attn/test/attntestmem.H | 466 |
7 files changed, 862 insertions, 1 deletions
diff --git a/src/usr/diag/attn/attn.C b/src/usr/diag/attn/attn.C index 496b659e5..dfe27d26e 100644 --- a/src/usr/diag/attn/attn.C +++ b/src/usr/diag/attn/attn.C @@ -34,6 +34,7 @@ #include "attntrace.H" #include "attnsvc.H" #include "attnproc.H" +#include "attnmem.H" using namespace std; using namespace PRDF; @@ -110,6 +111,7 @@ errlHndl_t Resolver::resolve( // resolvers for active attentions static ProcOps procOps; + static MemOps memOps; errlHndl_t err = 0; @@ -136,6 +138,15 @@ errlHndl_t Resolver::resolve( break; } + // query the mem resolver for active attentions + + err = memOps.resolve(i_proc, ipollMaskScomData, o_attentions); + + if(err) + { + break; + } + } while(0); return err; diff --git a/src/usr/diag/attn/attnfwd.H b/src/usr/diag/attn/attnfwd.H index 65aede329..ac6c49a42 100644 --- a/src/usr/diag/attn/attnfwd.H +++ b/src/usr/diag/attn/attnfwd.H @@ -44,6 +44,7 @@ class AttnListTest; class AttnOpsTest; class AttScomTest; class AttnProcTest; +class AttnMemTest; namespace ATTN { diff --git a/src/usr/diag/attn/attnmem.C b/src/usr/diag/attn/attnmem.C new file mode 100644 index 000000000..ebf60cd58 --- /dev/null +++ b/src/usr/diag/attn/attnmem.C @@ -0,0 +1,265 @@ +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/usr/diag/attn/attnmem.C $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ +/** + * @file attnmem.C + * + * @brief HBATTN Memory attention operations function definitions. + */ + +#include <errl/errlmanager.H> +#include <targeting/common/targetservice.H> +#include "attnmem.H" +#include "attnlist.H" +#include "attntarget.H" + +using namespace std; +using namespace PRDF; +using namespace TARGETING; +using namespace ERRORLOG; + +namespace ATTN +{ + +errlHndl_t MemOps::mask(const AttnData & i_data) +{ + errlHndl_t err = 0; + + do { + + TargetHandle_t proc = getTargetService().getProc(i_data.targetHndl); + + mutex_lock(&iv_mutex); + + bool mask = iv_maskState[proc] == 0; + + iv_maskState[proc]++; + + mutex_unlock(&iv_mutex); + + if(mask) + { + uint64_t ipollMaskWriteBits = 0; + + IPOLL::getCheckbits(HOST, ipollMaskWriteBits); + + err = modifyScom(proc, IPOLL::address, + ipollMaskWriteBits, SCOM_OR); + + if(err) + { + break; + } + } + + + } while(0); + + return err; +} + +errlHndl_t MemOps::unmask(const AttnData & i_data) +{ + errlHndl_t err = 0; + + do { + + TargetHandle_t proc = getTargetService().getProc(i_data.targetHndl); + + mutex_lock(&iv_mutex); + + iv_maskState[proc]--; + + bool unmask = iv_maskState[proc] == 0; + + if(unmask) + { + iv_maskState.erase(proc); + } + + mutex_unlock(&iv_mutex); + + if(unmask) + { + uint64_t ipollMaskWriteBits = 0; + + IPOLL::getCheckbits(HOST, ipollMaskWriteBits); + + err = modifyScom(proc, IPOLL::address, + ~ipollMaskWriteBits, SCOM_AND); + + if(err) + { + break; + } + } + + } while(0); + + return err; +} + +errlHndl_t MemOps::query(const AttnData & i_attnToCheck, bool & o_active) +{ + errlHndl_t err = 0; + + uint64_t checkbits = 0, scomData = 0; + TargetHandle_t mem = i_attnToCheck.targetHndl; + + do + { + TargetHandle_t mcs = getTargetService().getMcs(mem); + + MCI::getCheckbits(i_attnToCheck.attnType, checkbits); + + err = getScom(mcs, MCI::address, scomData); + + if(err) + { + break; + } + + if(scomData & checkbits) + { + o_active = true; + } + else + { + o_active = false; + } + + } while(0); + + return err; +} + +struct ResolveMcsArgs +{ + TargetHandle_t proc; + AttentionList * list; + MemOps * ops; +}; + +void resolveMcs(uint64_t i_mcs, void * i_data) +{ + ResolveMcsArgs * args = static_cast<ResolveMcsArgs *>(i_data); + + uint64_t mciFirScomData; + + TargetHandle_t mcs = getTargetService().getMcs(args->proc, i_mcs); + + // read the MCI fir to determine what type of attention + // centaur reporting + + errlHndl_t err = getScom(mcs, MCI::address, mciFirScomData); + + if(err) + { + errlCommit(err, HBATTN_COMP_ID); + } + else + { + // pick the highest priority attention + + for(uint64_t type = INVALID_ATTENTION_TYPE; + type != END_ATTENTION_TYPE; + ++type) + { + uint64_t mask; + + if(!MCI::getCheckbits(type, mask)) + { + // this object doesn't support + // this attention type + + continue; + } + + if(mask & mciFirScomData) + { + AttnData d; + d.targetHndl = getTargetService().getMembuf(mcs); + + d.attnType = static_cast<ATTENTION_VALUE_TYPE>(type); + + args->list->add(Attention(d, args->ops)); + break; + } + } + } +} + +errlHndl_t MemOps::resolve( + TargetHandle_t i_proc, + uint64_t i_typeMask, + AttentionList & o_attentions) +{ + errlHndl_t err = 0; + + uint64_t gp1ScomData = 0, hostMask = 0; + vector<uint64_t> mcsPositions; + + IPOLL::getCheckbits(HOST, hostMask); + + do { + + if(hostMask & i_typeMask) + { + // host attentions are masked.... + + break; + } + + // get the nest_gp1 register content and decode + // (get a list of membufs reporting attentions) + + err = getScom(i_proc, GP1::address, gp1ScomData); + + if(err) + { + break; + } + + ResolveMcsArgs args; + + args.proc = i_proc; + args.list = &o_attentions; + args.ops = this; + + GP1::forEach(gp1ScomData, &args, &resolveMcs); + + } while(0); + + return err; +} + +MemOps::MemOps() +{ + mutex_init(&iv_mutex); +} + +MemOps::~MemOps() +{ + mutex_destroy(&iv_mutex); +} +} diff --git a/src/usr/diag/attn/attnmem.H b/src/usr/diag/attn/attnmem.H new file mode 100644 index 000000000..96c0734d0 --- /dev/null +++ b/src/usr/diag/attn/attnmem.H @@ -0,0 +1,117 @@ +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/usr/diag/attn/attnmem.H $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ +#ifndef __ATTN_ATTNMEM_H +#define __ATTN_ATTNMEM_H + +/** + * @file attnmem.H + * + * @brief HBATTN memory attention operations definition. + */ + +#include "attnops.H" +#include <map> + +namespace ATTN +{ + +/** + * @brief MemOps ATTN memory attention operations definition. + */ +class MemOps : public AttentionOps +{ + public: + + /** + * @brief mask Mask this attention. + * + * @param[in] i_data The attention to mask. + * + * @retval[0] No error. + * @retval[!0] Unexpected error occurred. + */ + errlHndl_t mask(const PRDF::AttnData & i_data); + + /** + * @brief unmask Unmask this attention. + * + * @param[in] i_data The attention to unmask. + * + * @retval[0] No error. + * @retval[!0] Unexpected error occurred. + */ + errlHndl_t unmask(const PRDF::AttnData & i_data); + + /** + * @brief query Test to see if this attention is active. + * + * @param[in] i_data The attention to query. + * @param[out] o_active true if attention is active. + * + * @retval[0] No error. + * @retval[!0] Unexpected error occurred. + */ + errlHndl_t query(const PRDF::AttnData & i_data, bool & o_active); + + /** + * @brief resolve Find attentions of the supplied type on the + * supplied target. + * + * @param[in] i_proc The proc on which to look for attentions. + * @param[in] i_typeMask The types of attentions to look for. + * @param[out] o_attentions Where to put attentions when found. + * + * @retval[0] No error. + * @retval[!0] Unexpected error occurred. + */ + errlHndl_t resolve( + TARGETING::TargetHandle_t i_proc, + uint64_t i_typeMask, + AttentionList & o_attentions); + + /** + * @brief dtor + */ + ~MemOps(); + + /** + * @brief ctor + */ + MemOps(); + + private: + + /** + * @brief iv_maskState Proc target / ipoll host mask state + * association map. + */ + std::map<TARGETING::TargetHandle_t, uint64_t> iv_maskState; + + /** + * @brief protection for iv_maskState + */ + mutex_t iv_mutex; +}; +} +#endif diff --git a/src/usr/diag/attn/attnsvc.H b/src/usr/diag/attn/attnsvc.H index b0574cbeb..c31074742 100644 --- a/src/usr/diag/attn/attnsvc.H +++ b/src/usr/diag/attn/attnsvc.H @@ -255,6 +255,7 @@ class Service */ friend class ::AttnSvcTest; friend class ::AttnProcTest; + friend class ::AttnMemTest; }; } #endif diff --git a/src/usr/diag/attn/makefile b/src/usr/diag/attn/makefile index 1b7fcdb3f..482913889 100644 --- a/src/usr/diag/attn/makefile +++ b/src/usr/diag/attn/makefile @@ -27,7 +27,7 @@ EXTRAINCDIR += ${ROOTPATH}/src/include/usr/diag MODULE = attn OBJS = attntrace.o attn.o attnsvc.o attnlist.o attnbits.o attntarget.o \ - attnscom.o attnproc.o + attnscom.o attnproc.o attnmem.o SUBDIRS = test.d diff --git a/src/usr/diag/attn/test/attntestmem.H b/src/usr/diag/attn/test/attntestmem.H new file mode 100644 index 000000000..38046df89 --- /dev/null +++ b/src/usr/diag/attn/test/attntestmem.H @@ -0,0 +1,466 @@ +/* IBM_PROLOG_BEGIN_TAG + * This is an automatically generated prolog. + * + * $Source: src/usr/diag/attn/test/attntestmem.H $ + * + * IBM CONFIDENTIAL + * + * COPYRIGHT International Business Machines Corp. 2012 + * + * p1 + * + * Object Code Only (OCO) source materials + * Licensed Internal Code Source Materials + * IBM HostBoot Licensed Internal Code + * + * The source code for this program is not published or other- + * wise divested of its trade secrets, irrespective of what has + * been deposited with the U.S. Copyright Office. + * + * Origin: 30 + * + * IBM_PROLOG_END_TAG + */ +#ifndef __TEST_ATTNTESTMEM_H +#define __TEST_ATTNTESTMEM_H + +/** + * @file attntestmem.H + * + * @brief Unit test for the attnmem module. + */ + +#include "../attnmem.H" +#include "../attnsvc.H" +#include "attntest.H" +#include "attncomp.H" +#include "attnfakesys.H" +#include "attnfakemcs.H" +#include "attnfakegp1.H" +#include "attnfakeipoll.H" +#include "attnfakepresenter.H" +#include "attnfakeprd.H" +#include "attnrandsource.H" +#include "attnfaketarget.H" +#include "attnvalidate.H" +#include <cxxtest/TestSuite.H> +#include <sys/time.h> + +using namespace ATTN; +using namespace std; + +/** + * @brief AttnMemTest Unit test for the attnmem module. + */ +class AttnMemTest: public CxxTest::TestSuite +{ + public: + + /** + * @brief testMask Unit test for the + * mask method. + */ + void testMask(void) + { + TS_TRACE(ENTER_MRK "testMask"); + + static const uint64_t iterations = 100; + static const uint64_t targetPoolSize = 8; + + errlHndl_t err = 0; + + MemOps ops; + AttnData d; + + FakeSystem system; + FakeMemTargetService targetSvc(targetPoolSize); + + TargetHandleList membufs; + + targetSvc.getAllChips(membufs, TYPE_MEMBUF); + + targetSvc.installTargetService(); + system.installScomImpl(); + + for(uint64_t it = 0; it < iterations; ++it) + { + d.targetHndl = *(&membufs[0] + randint(0, membufs.size() -1)); + d.attnType = getRandomAttentionType(); + + TargetHandle_t proc = targetSvc.getProc(d.targetHndl); + + // put some random data in the mask register + + uint64_t randomData = randint(0, 0xffffffff); + uint64_t maskbits = 0; + + if(!IPOLL::getCheckbits(HOST, maskbits)) + { + TS_FAIL("unexpected error calling getCheckbits"); + break; + } + + randomData = randomData & ~maskbits; + + err = putScom( + proc, + IPOLL::address, + randomData); + if(err) + { + TS_FAIL("unexpected error calling putscom"); + break; + } + + err = ops.mask(d); + + if(err) + { + TS_FAIL("unexpected error masking attention"); + break; + } + + uint64_t data = 0; + err = getScom(proc, IPOLL::address, data); + if(err) + { + TS_FAIL("unexpected error calling getscom"); + break; + } + + // verify that the attn was masked, and that + // other bits weren't touched + + if(!(data & maskbits)) + { + TS_FAIL("attention not masked"); + break; + } + + if((data & ~maskbits) != randomData) + { + TS_FAIL("unexpected data in mask register"); + break; + } + + // clean up by unmasking + + err = ops.unmask(d); + + if(err) + { + TS_FAIL("unexpected error unmasking attention"); + break; + } + } + + TS_TRACE(EXIT_MRK "testMask"); + } + + /** + * @brief testUnmask Unit test for the + * unmask method. + */ + void testUnmask(void) + { + TS_TRACE(ENTER_MRK "testUnmask"); + + static const uint64_t iterations = 100; + static const uint64_t targetPoolSize = 8; + + errlHndl_t err = 0; + + MemOps ops; + AttnData d; + + FakeSystem system; + FakeMemTargetService targetSvc(targetPoolSize); + + TargetHandleList membufs; + + targetSvc.getAllChips(membufs, TYPE_MEMBUF); + + system.installScomImpl(); + targetSvc.installTargetService(); + + for(uint64_t it = 0; it < iterations; ++it) + { + d.targetHndl = *(&membufs[0] + randint(0, membufs.size() -1)); + d.attnType = getRandomAttentionType(); + + TargetHandle_t proc = targetSvc.getProc(d.targetHndl); + + // start by masking + + err = ops.mask(d); + + if(err) + { + TS_FAIL("unexpected error masking attention"); + break; + } + + // put some random data in the mask register + + uint64_t randomData = randint(0, 0xffffffff); + uint64_t maskbits = 0; + + if(!IPOLL::getCheckbits(HOST, maskbits)) + { + TS_FAIL("unexpected error calling getCheckbits"); + break; + } + + randomData = randomData | maskbits; + + err = putScom(proc, IPOLL::address, randomData); + if(err) + { + TS_FAIL("unexpected error calling putscom"); + break; + } + + err = ops.unmask(d); + + if(err) + { + TS_FAIL("unexpected error masking attention"); + break; + } + + uint64_t data = 0; + err = getScom(proc, IPOLL::address, data); + if(err) + { + TS_FAIL("unexpected error calling getscom"); + break; + } + + // verify that the attn was masked, and that + // other bits weren't touched + + if(!(data & ~maskbits)) + { + TS_FAIL("attention not unmasked"); + break; + } + + if((data | maskbits) != randomData) + { + TS_FAIL("unexpected data in mask register"); + break; + } + } + + TS_TRACE(EXIT_MRK "testUnmask"); + } + + /** + * @brief testQuery Unit test for the + * query method. + */ + void testQuery(void) + { + static const uint64_t iterations = 100; + static const uint64_t targetPoolSize = 8; + + TS_TRACE(ENTER_MRK "testQuery"); + + errlHndl_t err = 0; + + MemOps ops; + AttnData d; + + FakeSystem system; + FakeMemTargetService targetSvc(targetPoolSize); + + TargetHandleList membufs; + + targetSvc.getAllChips(membufs, TYPE_MEMBUF); + + FakeMcs rec(RECOVERABLE), xstp(CHECK_STOP), special(SPECIAL); + + system.installScomImpl(); + + xstp.install(system); + special.install(system); + rec.install(system); + + targetSvc.installTargetService(); + + for(uint64_t it = 0; it < iterations; ++it) + { + bool result; + + d.targetHndl = *(&membufs[0] + randint(0, membufs.size() -1)); + d.attnType = getRandomAttentionType(); + + // set the error in hardware + + err = system.putAttentions(AttnList(1, d)); + if(err) + { + TS_FAIL("unexpected error calling putAttentions"); + break; + } + + err = ops.query(d, result); + + if(err) + { + TS_FAIL("unexpected error calling query"); + break; + } + + if(!result) + { + TS_FAIL("expected attention"); + break; + } + + // clear the error in hardware + + err = system.clearAttention(d); + if(err) + { + TS_FAIL("unexpected error calling clearAttention"); + break; + } + + err = ops.query(d, result); + + if(err) + { + TS_FAIL("unexpected error calling query"); + break; + } + + if(result) + { + TS_FAIL("did not expect attention"); + break; + } + } + + TS_TRACE(EXIT_MRK "testQuery"); + } + + /** + * @brief testAttentions Unit test for the + * attnmem module. + */ + void testAttentions() + { + static const uint64_t targetPoolSize = 8; + static const uint64_t iterations = 5; + static const uint64_t maxAttentionsPerIteration = 5; + + TS_TRACE(ENTER_MRK "testAttentions"); + + errlHndl_t err = 0; + + Service svc; + + FakePresenter presenter; + FakeSystem system; + + FakeMemTargetService targetSvc(targetPoolSize); + + TargetHandleList membufs; + + targetSvc.getAllChips(membufs, TYPE_MEMBUF); + + FakeIpoll hostIpoll(HOST, presenter); + FakeMcs rec(RECOVERABLE), xstp(CHECK_STOP), special(SPECIAL); + FakeGp1 gp1; + + Validator v; + + xstp.install(system); + special.install(system); + rec.install(system); + gp1.install(system); + hostIpoll.install(system); + v.install(system); + + system.installScomImpl(); + + targetSvc.installTargetService(); + + RandSource source( + iterations, + maxAttentionsPerIteration, + system, + &membufs[0], + &membufs[0] + membufs.size()); + + FakePrd prd(system); + + prd.installPrd(); + + do + { + err = svc.start(); + + if(err) + { + TS_FAIL("unexpected error starting service"); + break; + } + + + if(!presenter.start(svc.iv_intrTaskQ)) + { + TS_FAIL("unexpected error starting fake presenter"); + break; + } + + if(!source.start()) + { + TS_FAIL("unexpected error starting source"); + break; + } + + // wait for the testcase to finish injecting attentions + + if(!source.wait()) + { + TS_FAIL("unexpected error waiting for source"); + break; + } + + // wait for the the service to handle all the attentions + TS_TRACE("Waiting for attentions to be cleared."); + + if(!system.wait(TEN_CTX_SWITCHES_NS * iterations * 100)) + { + TS_FAIL("Attentions still present on system."); + + system.dump(); + break; + } + + } while(0); + + err = svc.stop(); + + if(err) + { + TS_FAIL("unexpected error stopping service"); + + delete err; + } + + presenter.stop(); + + if(!v.empty()) + { + TS_FAIL("unexpected result after injecting attentions"); + + v.dump(); + } + + TS_TRACE(EXIT_MRK "testAttentions"); + } +}; +#endif |