@@ -3899,6 +3899,11 @@ ServerUncorePowerState PCM::getServerUncorePowerState(uint32 socket)
38993899 for (uint32 cnt=0 ;cnt<4 ;++cnt)
39003900 result.EDCCounter [channel][cnt] = server_pcicfg_uncore[socket]->getEDCCounter (channel,cnt);
39013901 }
3902+ for (uint32 controller = 0 ; controller < (uint32)server_pcicfg_uncore[socket]->getNumMC (); ++controller)
3903+ {
3904+ for (uint32 cnt=0 ;cnt<4 ;++cnt)
3905+ result.M2MCounter [controller][cnt] = server_pcicfg_uncore[socket]->getM2MCounter (controller,cnt);
3906+ }
39023907 server_pcicfg_uncore[socket]->unfreezeCounters ();
39033908 }
39043909 if (MSR.size ())
@@ -4009,12 +4014,21 @@ static const uint32 UPI_DEV_IDS[] = {
40094014 0x2058
40104015};
40114016
4017+ static const uint32 M2M_DEV_IDS[] = {
4018+ 0x2066
4019+ };
4020+
40124021PCM_Util::Mutex ServerPCICFGUncore::socket2busMutex;
40134022std::vector<std::pair<uint32,uint32> > ServerPCICFGUncore::socket2iMCbus;
40144023std::vector<std::pair<uint32,uint32> > ServerPCICFGUncore::socket2UPIbus;
4024+ std::vector<std::pair<uint32,uint32> > ServerPCICFGUncore::socket2M2Mbus;
40154025
40164026void ServerPCICFGUncore::initSocket2Bus (std::vector<std::pair<uint32, uint32> > & socket2bus, uint32 device, uint32 function, const uint32 DEV_IDS[], uint32 devIdsSize)
40174027{
4028+ if (device == PCM_INVALID_DEV_ADDR || function == PCM_INVALID_FUNC_ADDR)
4029+ {
4030+ return ;
4031+ }
40184032 PCM_Util::Mutex::Scope _ (socket2busMutex);
40194033 if (!socket2bus.empty ()) return ;
40204034
@@ -4107,9 +4121,11 @@ PciHandleType * ServerPCICFGUncore::createIntelPerfMonDevice(uint32 groupnr_, in
41074121ServerPCICFGUncore::ServerPCICFGUncore (uint32 socket_, const PCM * pcm) :
41084122 iMCbus(-1 )
41094123 , UPIbus(-1 )
4124+ , M2Mbus(-1 )
41104125 , groupnr(0 )
41114126 , qpi_speed(0 )
41124127 , num_imc(0 )
4128+ , num_imc_channels1(0 )
41134129{
41144130
41154131#define PCM_PCICFG_MC_INIT (controller, channel, arch ) \
@@ -4122,6 +4138,14 @@ ServerPCICFGUncore::ServerPCICFGUncore(uint32 socket_, const PCM * pcm) :
41224138 EDCX_ECLK_REGISTER_DEV_ADDR[controller] = arch##_EDC##controller##_##clock##_REGISTER_DEV_ADDR; \
41234139 EDCX_ECLK_REGISTER_FUNC_ADDR[controller] = arch##_EDC##controller##_##clock##_REGISTER_FUNC_ADDR;
41244140
4141+ #define PCM_PCICFG_M2M_INIT (x, arch ) \
4142+ M2M_REGISTER_DEV_ADDR[x] = arch##_M2M_##x##_REGISTER_DEV_ADDR; \
4143+ M2M_REGISTER_FUNC_ADDR[x] = arch##_M2M_##x##_REGISTER_FUNC_ADDR;
4144+
4145+ M2M_REGISTER_DEV_ADDR[0 ] = PCM_INVALID_DEV_ADDR;
4146+ M2M_REGISTER_FUNC_ADDR[0 ] = PCM_INVALID_FUNC_ADDR;
4147+ M2M_REGISTER_DEV_ADDR[1 ] = PCM_INVALID_DEV_ADDR;
4148+ M2M_REGISTER_FUNC_ADDR[1 ] = PCM_INVALID_FUNC_ADDR;
41254149
41264150 if (cpu_model == PCM::JAKETOWN || cpu_model == PCM::IVYTOWN)
41274151 {
@@ -4155,6 +4179,9 @@ ServerPCICFGUncore::ServerPCICFGUncore(uint32 socket_, const PCM * pcm) :
41554179 PCM_PCICFG_MC_INIT (1 , 1 , SKX)
41564180 PCM_PCICFG_MC_INIT (1 , 2 , SKX)
41574181 PCM_PCICFG_MC_INIT (1 , 3 , SKX)
4182+
4183+ PCM_PCICFG_M2M_INIT (0 , SKX)
4184+ PCM_PCICFG_M2M_INIT (1 , SKX)
41584185 }
41594186 else if (cpu_model == PCM::KNL)
41604187 {
@@ -4184,12 +4211,26 @@ ServerPCICFGUncore::ServerPCICFGUncore(uint32 socket_, const PCM * pcm) :
41844211
41854212#undef PCM_PCICFG_MC_INIT
41864213#undef PCM_PCICFG_EDC_INIT
4214+ #undef PCM_PCICFG_M2M_INIT
41874215
4188- initSocket2Bus (socket2iMCbus, MCX_CHY_REGISTER_DEV_ADDR[0 ][0 ], MCX_CHY_REGISTER_FUNC_ADDR[0 ][0 ], IMC_DEV_IDS, (uint32)sizeof (IMC_DEV_IDS) / sizeof (IMC_DEV_IDS[0 ]));
41894216 const uint32 total_sockets_ = pcm->getNumSockets ();
41904217
4218+ initSocket2Bus (socket2M2Mbus, M2M_REGISTER_DEV_ADDR[0 ], M2M_REGISTER_FUNC_ADDR[0 ], M2M_DEV_IDS, (uint32)sizeof (M2M_DEV_IDS) / sizeof (M2M_DEV_IDS[0 ]));
4219+ if (total_sockets_ == socket2M2Mbus.size ())
4220+ {
4221+ groupnr = socket2M2Mbus[socket_].first ;
4222+ M2Mbus = socket2M2Mbus[socket_].second ;
4223+ }
4224+
4225+ initSocket2Bus (socket2iMCbus, MCX_CHY_REGISTER_DEV_ADDR[0 ][0 ], MCX_CHY_REGISTER_FUNC_ADDR[0 ][0 ], IMC_DEV_IDS, (uint32)sizeof (IMC_DEV_IDS) / sizeof (IMC_DEV_IDS[0 ]));
4226+
41914227 if (total_sockets_ == socket2iMCbus.size ())
41924228 {
4229+ if (total_sockets_ == socket2M2Mbus.size () && socket2iMCbus[socket_].first != socket2M2Mbus[socket_].first )
4230+ {
4231+ std::cerr << " PCM error: mismatching PCICFG group number for M2M and IMC perfmon devices." << std::endl;
4232+ M2Mbus = -1 ;
4233+ }
41934234 groupnr = socket2iMCbus[socket_].first ;
41944235 iMCbus = socket2iMCbus[socket_].second ;
41954236
@@ -4226,7 +4267,7 @@ ServerPCICFGUncore::ServerPCICFGUncore(uint32 socket_, const PCM * pcm) :
42264267 PCM_PCICFG_SETUP_MC_HANDLE (0 ,3 )
42274268
42284269 if (!imcHandles.empty ()) ++num_imc; // at least one memory controller
4229- const size_t num_imc_channels1 = (size_t )imcHandles.size ();
4270+ num_imc_channels1 = (uint32 )imcHandles.size ();
42304271
42314272 PCM_PCICFG_SETUP_MC_HANDLE (1 ,0 )
42324273 PCM_PCICFG_SETUP_MC_HANDLE (1 ,1 )
@@ -4264,6 +4305,20 @@ ServerPCICFGUncore::ServerPCICFGUncore(uint32 socket_, const PCM * pcm) :
42644305#undef PCM_PCICFG_SETUP_EDC_HANDLE
42654306 }
42664307
4308+ #define PCM_PCICFG_SETUP_M2M_HANDLE (x ) \
4309+ if (M2Mbus >= 0 && M2M_REGISTER_DEV_ADDR[x] != PCM_INVALID_DEV_ADDR && \
4310+ M2M_REGISTER_FUNC_ADDR[x] != PCM_INVALID_FUNC_ADDR ) \
4311+ { \
4312+ PciHandleType * handle = createIntelPerfMonDevice (groupnr, M2Mbus, \
4313+ M2M_REGISTER_DEV_ADDR[x], M2M_REGISTER_FUNC_ADDR[x], true ); \
4314+ if (handle) m2mHandles.push_back (std::shared_ptr<PciHandleType>(handle));\
4315+ }
4316+
4317+ PCM_PCICFG_SETUP_M2M_HANDLE (0 )
4318+ PCM_PCICFG_SETUP_M2M_HANDLE (1 )
4319+
4320+ #undef PCM_PCICFG_SETUP_M2M_HANDLE
4321+
42674322 if (total_sockets_ == 1 ) {
42684323 /*
42694324 * For single socket systems, do not worry at all about QPI ports. This
@@ -4273,13 +4328,15 @@ ServerPCICFGUncore::ServerPCICFGUncore(uint32 socket_, const PCM * pcm) :
42734328 * is possible with single socket systems.
42744329 */
42754330 qpiLLHandles.clear ();
4276- std::cerr << " On the socket detected " << num_imc << " memory controllers with total number of " << imcHandles.size () << " channels. " << std::endl;
4331+ std::cerr << " On the socket detected " << num_imc << " memory controllers with total number of " << imcHandles.size () << " channels. " <<
4332+ m2mHandles.size () << " M2M (mesh to memory) blocks detected." << std::endl;
42774333 return ;
42784334 }
42794335
42804336#ifdef PCM_NOQPI
42814337 qpiLLHandles.clear ();
4282- std::cerr << num_imc<<" memory controllers detected with total number of " << imcHandles.size () <<" channels. " << std::endl;
4338+ std::cerr << num_imc<<" memory controllers detected with total number of " << imcHandles.size () <<" channels. " <<
4339+ m2mHandles.size () << " M2M (mesh to memory) blocks detected." << std::endl;
42834340 return ;
42844341#else
42854342
@@ -4397,7 +4454,20 @@ ServerPCICFGUncore::ServerPCICFGUncore(uint32 socket_, const PCM * pcm) :
43974454#endif
43984455 std::cerr << " Socket " <<socket_<<" : " <<
43994456 num_imc<<" memory controllers detected with total number of " << getNumMCChannels () <<" channels. " <<
4400- getNumQPIPorts ()<< " QPI ports detected." <<std::endl;
4457+ getNumQPIPorts ()<< " QPI ports detected." <<
4458+ " " <<m2mHandles.size () << " M2M (mesh to memory) blocks detected." << std::endl;
4459+ }
4460+
4461+ size_t ServerPCICFGUncore::getNumMCChannels (const uint32 controller) const
4462+ {
4463+ switch (controller)
4464+ {
4465+ case 0 :
4466+ return num_imc_channels1;
4467+ case 1 :
4468+ return imcHandles.size () - num_imc_channels1;
4469+ }
4470+ return 0 ;
44014471}
44024472
44034473ServerPCICFGUncore::~ServerPCICFGUncore ()
@@ -4474,6 +4544,8 @@ void ServerPCICFGUncore::programServerUncoreMemoryMetrics(int rankA, int rankB,
44744544 programIMC (MCCntConfig);
44754545 if (cpu_model == PCM::KNL) programEDC (EDCCntConfig);
44764546
4547+ programM2M ();
4548+
44774549 qpiLLHandles.clear (); // no QPI events used
44784550 return ;
44794551}
@@ -4584,6 +4656,29 @@ void ServerPCICFGUncore::cleanupQPIHandles()
45844656}
45854657
45864658uint64 ServerPCICFGUncore::getImcReads ()
4659+ {
4660+ return getImcReadsForChannels ((uint32)0 , (uint32)imcHandles.size ());
4661+ }
4662+
4663+ uint64 ServerPCICFGUncore::getImcReadsForController (uint32 controller)
4664+ {
4665+ uint32 beginChannel = 0 ;
4666+ uint32 endChannel = 0 ;
4667+ switch (controller)
4668+ {
4669+ case 0 :
4670+ beginChannel = 0 ;
4671+ endChannel = num_imc_channels1;
4672+ break ;
4673+ case 1 :
4674+ beginChannel = num_imc_channels1;
4675+ endChannel = (uint32)imcHandles.size ();
4676+ break ;
4677+ }
4678+ return getImcReadsForChannels (beginChannel, endChannel);
4679+ }
4680+
4681+ uint64 ServerPCICFGUncore::getImcReadsForChannels (uint32 beginChannel, uint32 endChannel)
45874682{
45884683 uint64 result = 0 ;
45894684 uint64 MC_CH_PCI_PMON_CTR0_ADDR = 0 ;
@@ -4592,19 +4687,17 @@ uint64 ServerPCICFGUncore::getImcReads()
45924687 const uint32 cpu_model = pcm->getCPUModel ();
45934688 if (cpu_model == PCM::KNL) {
45944689 MC_CH_PCI_PMON_CTR0_ADDR = KNX_MC_CH_PCI_PMON_CTR0_ADDR;
4595- } else {
4690+ }
4691+ else {
45964692 MC_CH_PCI_PMON_CTR0_ADDR = XPF_MC_CH_PCI_PMON_CTR0_ADDR;
45974693 }
4598-
4599- // std::cout << "DEBUG: imcHandles.size() = " << imcHandles.size() << std::endl;
4600- for (uint32 i = 0 ; i < (uint32)imcHandles.size (); ++i)
4694+ for (uint32 i = beginChannel; i < endChannel && i < imcHandles.size (); ++i)
46014695 {
46024696 uint64 value = 0 ;
46034697 imcHandles[i]->read64 (MC_CH_PCI_PMON_CTR0_ADDR, &value);
4604- // std::cout << "DEBUG: getImcReads() with fd = " << imcHandles[i]->fd << " value = " << value << std::endl;
4698+ // std::cout << "DEBUG: getImcReads() with fd = " << imcHandles[i]->fd << " value = " << value << std::endl;
46054699 result += value;
46064700 }
4607-
46084701 return result;
46094702}
46104703
@@ -4950,13 +5043,50 @@ void ServerPCICFGUncore::programEDC(const uint32 * EDCCntConfig)
49505043 }
49515044}
49525045
5046+ void ServerPCICFGUncore::programM2M ()
5047+ {
5048+ #if 0
5049+ PCM * pcm = PCM::getInstance();
5050+ const uint32 cpu_model = pcm->getCPUModel();
5051+ if (cpu_model == PCM::SKX)
5052+ #endif
5053+ {
5054+ for (auto & m2mHandle : m2mHandles)
5055+ {
5056+ // freeze enable
5057+ m2mHandle->write32 (M2M_PCI_PMON_BOX_CTL_ADDR, UNC_PMON_UNIT_CTL_RSV);
5058+ // freeze
5059+ m2mHandle->write32 (M2M_PCI_PMON_BOX_CTL_ADDR, UNC_PMON_UNIT_CTL_RSV + UNC_PMON_UNIT_CTL_FRZ);
5060+
5061+ #ifdef PCM_UNCORE_PMON_BOX_CHECK_STATUS
5062+ uint32 val = 0 ;
5063+ m2mHandle->write32 (M2M_PCI_PMON_BOX_CTL_ADDR, &val);
5064+ if ((val & UNC_PMON_UNIT_CTL_VALID_BITS_MASK) != (extra + UNC_PMON_UNIT_CTL_FRZ))
5065+ {
5066+ std::cerr << " ERROR: M2M counter programming seems not to work. M2M_PCI_PMON_BOX_CTL=0x" << std::hex << val << std::endl;
5067+ std::cerr << " Please see BIOS options to enable the export of performance monitoring devices." << std::endl;
5068+ }
5069+ #endif
5070+
5071+ m2mHandle->write32 (M2M_PCI_PMON_CTL0_ADDR, M2M_PCI_PMON_CTL_EN);
5072+ // TAG_HIT.NM_DRD_HIT_* events (CLEAN | DIRTY)
5073+ m2mHandle->write32 (M2M_PCI_PMON_CTL0_ADDR, M2M_PCI_PMON_CTL_EN + M2M_PCI_PMON_CTL_EVENT (0x2c ) + M2M_PCI_PMON_CTL_UMASK (3 ));
5074+ m2mHandle->write32 (M2M_PCI_PMON_CTL3_ADDR, M2M_PCI_PMON_CTL_EN); // CLOCKTICKS
5075+ // reset counters values
5076+ m2mHandle->write32 (M2M_PCI_PMON_BOX_CTL_ADDR, UNC_PMON_UNIT_CTL_RSV + UNC_PMON_UNIT_CTL_FRZ + UNC_PMON_UNIT_CTL_RST_COUNTERS);
5077+
5078+ // unfreeze counters
5079+ m2mHandle->write32 (M2M_PCI_PMON_BOX_CTL_ADDR, UNC_PMON_UNIT_CTL_RSV);
5080+ }
5081+ }
5082+ }
5083+
49535084void ServerPCICFGUncore::freezeCounters ()
49545085{
49555086 uint64 MC_CH_PCI_PMON_BOX_CTL_ADDR = 0 ;
49565087 uint64 EDC_CH_PCI_PMON_BOX_CTL_ADDR = 0 ;
49575088 const uint32 cpu_model = PCM::getInstance ()->getCPUModel ();
49585089 const uint32 extra = (cpu_model == PCM::SKX)?UNC_PMON_UNIT_CTL_RSV:UNC_PMON_UNIT_CTL_FRZ_EN;
4959- const uint32 extraIMC = (cpu_model == PCM::SKX)?UNC_PMON_UNIT_CTL_RSV:UNC_PMON_UNIT_CTL_FRZ_EN;
49605090 if (cpu_model == PCM::KNL) {
49615091 MC_CH_PCI_PMON_BOX_CTL_ADDR = KNX_MC_CH_PCI_PMON_BOX_CTL_ADDR;
49625092 EDC_CH_PCI_PMON_BOX_CTL_ADDR = KNX_EDC_CH_PCI_PMON_BOX_CTL_ADDR;
@@ -4969,19 +5099,22 @@ void ServerPCICFGUncore::freezeCounters()
49695099 }
49705100 for (size_t i = 0 ; i < (size_t )imcHandles.size (); ++i)
49715101 {
4972- imcHandles[i]->write32 (MC_CH_PCI_PMON_BOX_CTL_ADDR, extraIMC + UNC_PMON_UNIT_CTL_FRZ);
5102+ imcHandles[i]->write32 (MC_CH_PCI_PMON_BOX_CTL_ADDR, extra + UNC_PMON_UNIT_CTL_FRZ);
49735103 }
49745104 for (size_t i = 0 ; i < (size_t )edcHandles.size (); ++i)
49755105 {
49765106 edcHandles[i]->write32 (EDC_CH_PCI_PMON_BOX_CTL_ADDR, UNC_PMON_UNIT_CTL_FRZ_EN + UNC_PMON_UNIT_CTL_FRZ);
49775107 }
5108+ for (auto & handle: m2mHandles)
5109+ {
5110+ handle->write32 (M2M_PCI_PMON_BOX_CTL_ADDR, extra + UNC_PMON_UNIT_CTL_FRZ);
5111+ }
49785112}
49795113
49805114void ServerPCICFGUncore::unfreezeCounters ()
49815115{
49825116 const uint32 cpu_model = PCM::getInstance ()->getCPUModel ();
49835117 const uint32 extra = (cpu_model == PCM::SKX)?UNC_PMON_UNIT_CTL_RSV:UNC_PMON_UNIT_CTL_FRZ_EN;
4984- const uint32 extraIMC = (cpu_model == PCM::SKX)?UNC_PMON_UNIT_CTL_RSV:UNC_PMON_UNIT_CTL_FRZ_EN;
49855118 uint64 MC_CH_PCI_PMON_BOX_CTL_ADDR = 0 ;
49865119 uint64 EDC_CH_PCI_PMON_BOX_CTL_ADDR = 0 ;
49875120 if (cpu_model == PCM::KNL) {
@@ -4997,12 +5130,16 @@ void ServerPCICFGUncore::unfreezeCounters()
49975130 }
49985131 for (size_t i = 0 ; i < (size_t )imcHandles.size (); ++i)
49995132 {
5000- imcHandles[i]->write32 (MC_CH_PCI_PMON_BOX_CTL_ADDR, extraIMC );
5133+ imcHandles[i]->write32 (MC_CH_PCI_PMON_BOX_CTL_ADDR, extra );
50015134 }
50025135 for (size_t i = 0 ; i < (size_t )edcHandles.size (); ++i)
50035136 {
50045137 edcHandles[i]->write32 (EDC_CH_PCI_PMON_BOX_CTL_ADDR, UNC_PMON_UNIT_CTL_FRZ_EN);
50055138 }
5139+ for (auto & handle: m2mHandles)
5140+ {
5141+ handle->write32 (M2M_PCI_PMON_BOX_CTL_ADDR, extra);
5142+ }
50065143}
50075144
50085145uint64 ServerPCICFGUncore::getQPIClocks (uint32 port)
@@ -5165,6 +5302,33 @@ uint64 ServerPCICFGUncore::getEDCCounter(uint32 channel, uint32 counter)
51655302}
51665303
51675304
5305+ uint64 ServerPCICFGUncore::getM2MCounter (uint32 box, uint32 counter)
5306+ {
5307+ uint64 result = 0 ;
5308+
5309+ if (box < (uint32)m2mHandles.size ())
5310+ {
5311+ switch (counter)
5312+ {
5313+ case 0 :
5314+ m2mHandles[box]->read64 (M2M_PCI_PMON_CTR0_ADDR, &result);
5315+ break ;
5316+ case 1 :
5317+ m2mHandles[box]->read64 (M2M_PCI_PMON_CTR1_ADDR, &result);
5318+ break ;
5319+ case 2 :
5320+ m2mHandles[box]->read64 (M2M_PCI_PMON_CTR2_ADDR, &result);
5321+ break ;
5322+ case 3 :
5323+ m2mHandles[box]->read64 (M2M_PCI_PMON_CTR3_ADDR, &result);
5324+ break ;
5325+ }
5326+ }
5327+ // std::cout << "DEBUG: read "<< result << " from M2M box "<< box <<" counter " << counter << std::endl;
5328+ return result;
5329+ }
5330+
5331+
51685332uint64 ServerPCICFGUncore::getQPILLCounter (uint32 port, uint32 counter)
51695333{
51705334 uint64 result = 0 ;
0 commit comments