diff options
author | Zane Shelley <zshelle@us.ibm.com> | 2018-02-18 20:42:52 -0600 |
---|---|---|
committer | Zane C. Shelley <zshelle@us.ibm.com> | 2018-02-19 16:13:04 -0500 |
commit | 1275d064b04f96e767bfbf7b6777b73adf038ed6 (patch) | |
tree | 1d36ddd66f12b8c36c72cbecda3ad370743d7708 /src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C | |
parent | 9900129f86ae2fd82f59f643e71d15b5143959c2 (diff) | |
download | talos-hostboot-1275d064b04f96e767bfbf7b6777b73adf038ed6.tar.gz talos-hostboot-1275d064b04f96e767bfbf7b6777b73adf038ed6.zip |
PRD: Fixed address translation for Dynamic Memory Deallocation
Change-Id: Icfa317395362b6a4bc6663cfea832de0ef12d97c
CQ: SW417578
Backport: release-fips910
Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/54330
Tested-by: Jenkins Server <pfd-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP Build CI <op-jenkins+hostboot@us.ibm.com>
Tested-by: Jenkins OP HW <op-hw-jenkins+hostboot@us.ibm.com>
Tested-by: FSP CI Jenkins <fsp-CI-jenkins+hostboot@us.ibm.com>
Reviewed-by: Benjamin J. Weisenbeck <bweisenb@us.ibm.com>
Reviewed-by: Brian J. Stegmiller <bjs@us.ibm.com>
Reviewed-by: Caleb N. Palmer <cnpalmer@us.ibm.com>
Reviewed-by: Zane C. Shelley <zshelle@us.ibm.com>
Diffstat (limited to 'src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C')
-rw-r--r-- | src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C | 360 |
1 files changed, 140 insertions, 220 deletions
diff --git a/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C b/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C index 3615a4ca3..63143c0bb 100644 --- a/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C +++ b/src/usr/diag/prdf/plat/mem/prdfMemDynDealloc.C @@ -53,244 +53,167 @@ bool isEnabled() !isMfgAvpEnabled() && !isMfgHdatAvpEnabled() ); } -int32_t getRowsAndIntrlv( ExtensibleChip * i_chip, uint8_t i_dslct, - uint8_t &o_rows, bool &o_interleaved) +int32_t __getAddrConfig( ExtensibleChip * i_mcaChip, uint8_t i_dslct, + bool & o_twoDimmConfig, uint8_t & o_mrnkBits, + uint8_t & o_srnkBits, uint8_t & o_extraRowBits ) { - int32_t o_rc = SUCCESS; - o_rows = 0; - o_interleaved = false; + #define PRDF_FUNC "[MemDealloc::__getAddrConfig] " - SCAN_COMM_REGISTER_CLASS * addrTransReg = - i_chip->getRegister( "MC_ADDR_TRANS" ); + int32_t o_rc = SUCCESS; - o_rc = addrTransReg->Read(); + SCAN_COMM_REGISTER_CLASS * reg = i_mcaChip->getRegister( "MC_ADDR_TRANS" ); + o_rc = reg->Read(); if ( SUCCESS != o_rc ) { - PRDF_ERR("getRows Read failed on addrTransReg: chip=0x%08x", - i_chip->getHuid() ); + PRDF_ERR( PRDF_FUNC "Read failed on MC_ADDR_TRANS: i_mcaChip=0x%08x", + i_mcaChip->getHuid() ); return o_rc; } - if (addrTransReg->IsBitSet(i_dslct ? 31:15)) - o_rows = 18; - else if (addrTransReg->IsBitSet(i_dslct ? 30:14)) - o_rows = 17; - else if (addrTransReg->IsBitSet(i_dslct ? 29:13)) - o_rows = 16; - else - o_rows = 15; + o_twoDimmConfig = false; + if ( reg->IsBitSet(0) && reg->IsBitSet(16) ) + o_twoDimmConfig = true; + + o_mrnkBits = 0; + if ( reg->IsBitSet(i_dslct ? 21: 5) ) o_mrnkBits++; + if ( reg->IsBitSet(i_dslct ? 22: 6) ) o_mrnkBits++; + + o_srnkBits = 0; + if ( reg->IsBitSet(i_dslct ? 25: 9) ) o_srnkBits++; + if ( reg->IsBitSet(i_dslct ? 26:10) ) o_srnkBits++; + if ( reg->IsBitSet(i_dslct ? 27:11) ) o_srnkBits++; - if ( addrTransReg->IsBitSet(0) && addrTransReg->IsBitSet(16)) - o_interleaved = true; + // According to the hardware team, B2 is used for DDR4e which went away. If + // for some reason B2 is valid, there is definitely a bug. + if ( reg->IsBitSet(i_dslct ? 28:12) ) + { + PRDF_ERR( PRDF_FUNC "B2 enabled in MC_ADDR_TRANS: i_mcaChip=0x%08x " + "i_dslct=%d", i_mcaChip->getHuid(), i_dslct ); + return FAIL; + } + + o_extraRowBits = 0; + if ( reg->IsBitSet(i_dslct ? 29:13) ) o_extraRowBits++; + if ( reg->IsBitSet(i_dslct ? 30:14) ) o_extraRowBits++; + if ( reg->IsBitSet(i_dslct ? 31:15) ) o_extraRowBits++; return o_rc; + + #undef PRDF_FUNC } -void setRemainingRowBitsAndDimmSelect(uint8_t i_bit, //bit position in o_addr - uint64_t i_row, //row value from MemAddr - uint8_t i_numRows, //# of row bits - uint64_t i_dsclt, // dimm select - uint64_t &o_addr) // system address +uint64_t __reverseBits( uint64_t i_val, uint64_t i_numBits ) { - // Write bits R15..R17 followed by dimm select bit - uint8_t rowBit = 15; - while ( i_bit >= 0 && rowBit <= i_numRows ) + uint64_t o_val = 0; + + for ( uint64_t i = 0; i < i_numBits; i++ ) { - if (i_numRows == rowBit) - { - // We've finished writing row bits, now write the dimm select - // and we're done - o_addr |= (i_dsclt << (63-i_bit)); - break;; - } - else - { - // Set i_bit to rowBit - o_addr |= (((i_row >> (17-rowBit)) & 0x1) << (63-i_bit)); - ++rowBit; - --i_bit; - } + o_val <<= 1; + o_val |= i_val & 0x1; + i_val >>= 1; } - return; + + return o_val; } -int32_t getMcaPortAddr( ExtensibleChip * i_chip, MemAddr i_addr, - uint64_t & o_addr ) +uint64_t __maskBits( uint64_t i_val, uint64_t i_numBits ) { - #define PRDF_FUNC "[MemDealloc::getMcaPortAddr] " + uint64_t mask = (0xffffffffffffffffull >> i_numBits) << i_numBits; + return i_val & ~mask; +} +int32_t __getMcaPortAddr( ExtensibleChip * i_chip, MemAddr i_addr, + uint64_t & o_addr ) +{ int32_t o_rc = SUCCESS; + o_addr = 0; - TargetHandle_t tgt = i_chip->GetChipHandle(); - MemRank rnk = i_addr.getRank(); // Local vars for address fields - uint64_t col = i_addr.getCol(); // C3 C4 C5 C6 C7 C8 C9 - uint64_t row = i_addr.getRow(); // R0 R1 R2 .. R16 R17 - uint64_t bnk = i_addr.getBank(); // BG0 BG1 B0 B1 B2 - uint64_t srnk = rnk.getSlave(); // S0 S1 S2 - uint64_t mrnk = rnk.getRankSlct(); // M0 M1 - uint64_t dslct = rnk.getDimmSlct(); // 1 bit - - // number of masters and slaves per dimm - uint8_t mstrs = getNumMasterRanksPerDimm<TYPE_MCA>(tgt, dslct); - uint8_t slvs = getNumRanksPerDimm<TYPE_MCA>(tgt, dslct) / mstrs; - - uint8_t rowBits = 0; // Number of row bits used for an addr on this dimm - bool interleaved = false; // Whether dimm slot interleaving is used - o_rc = getRowsAndIntrlv( i_chip, dslct, rowBits, interleaved); - if (o_rc != SUCCESS) - return o_rc; - - // If we're not using 2 dimm slots, the DS bit should always be set to 0 - if (!interleaved) - dslct = 0; - - // Set Bits 33-0 - do { - // Bits 33-30 are common to all configs - // Set bit 33 to C3 - o_addr |= ((col & 0x40) << 24); - // Set bits 31 32 to BG0 BG1 - o_addr |= ((bnk & 0x18) << 28); - // Set bit 30 to B1 - o_addr |= ((bnk & 0x02) << 32); - - // Bit 29 - if ( slvs != 0 ) - { - // Set bit 29 to S2 - o_addr |= ((srnk & 0x01) << 34); - } - else if (mstrs > 1) - { - // Set bit 29 to M1 - o_addr |= ((mrnk & 0x01) << 34); - } - else if (interleaved) - { - // Set bit 29 to D - o_addr |= (dslct << 34); - } - else - { - // Set bit 29 to B0 - o_addr |= ((bnk & 0x04) << 32); - } - - //Bits 28-23 - if ( mstrs == 1 && slvs == 0 && !interleaved ) - { - // Set Bit 28 to C4 - o_addr |= ((col & 0x20) << 30); - // Set bits 23-27 to C9-C5 - o_addr |= ((col & 0x10) << 32); - o_addr |= ((col & 0x08) << 34); - o_addr |= ((col & 0x04) << 36); - o_addr |= ((col & 0x02) << 38); - o_addr |= ((col & 0x01) << 40); - } - else - { - // Set Bit 28 to B0 - o_addr |= ((bnk & 0x04) << 33); - // Set bits 23-27 to C8-C4 - o_addr |= ((col & 0x20) << 31); - o_addr |= ((col & 0x10) << 33); - o_addr |= ((col & 0x08) << 35); - o_addr |= ((col & 0x04) << 37); - o_addr |= ((col & 0x02) << 39); - } - - // Bits 22-8 - o_addr |= ((row & 0x00010) << 37); // R13 -> bit 22 - o_addr |= ((row & 0x20000) << 25); // R0 -> bit 21 - o_addr |= ((row & 0x10000) << 27); // R1 -> bit 20 - o_addr |= ((row & 0x08000) << 29); // R2 -> bit 19 - o_addr |= ((row & 0x04000) << 31); // R3 -> bit 18 - o_addr |= ((row & 0x02000) << 33); // R4 -> bit 17 - o_addr |= ((row & 0x01000) << 35); // R5 -> bit 16 - o_addr |= ((row & 0x00800) << 37); // R6 -> bit 15 - o_addr |= ((row & 0x00400) << 39); // R7 -> bit 14 - o_addr |= ((row & 0x00200) << 41); // R8 -> bit 13 - o_addr |= ((row & 0x00100) << 43); // R9 -> bit 12 - o_addr |= ((row & 0x00080) << 45); // R10 -> bit 11 - o_addr |= ((row & 0x00040) << 47); // R11 -> bit 10 - o_addr |= ((row & 0x00020) << 49); // R12 -> bit 9 - o_addr |= ((row & 0x00008) << 52); // R14 -> bit 8 - - // Bit 7 - if ( mstrs == 1 && slvs == 0 && !interleaved ) - { - // Set remaining row bits starting at bit 7 - setRemainingRowBitsAndDimmSelect(7, row, rowBits, dslct, o_addr); - break; - } - else - { - // Set bit 7 to C9 - o_addr |= ((col & 0x01) << 56); - } - - // Bit 6... - if (slvs >= 4) - { - // set bit 6 to S1 - o_addr |= ((srnk & 0x02) << 56); - } - else if (mstrs == 4 && slvs==0) - { - // set Bit 6 to M0 - o_addr |= ((mrnk & 0x02) << 56); - } - else if (mstrs == 2 && slvs == 2) - { - // Set Bit 6 to M1 - o_addr |= ((mrnk & 0x01) << 57); - } - else - { - // Set remaining bits starting at 6 - setRemainingRowBitsAndDimmSelect(6, row, rowBits, dslct, o_addr); - break; - } - - // Bit 5 - if (slvs >= 8) - { - // Set bit 5 to S0 - o_addr |= ((srnk & 0x04) << 56); - } - else if (mstrs == 2 && slvs == 4) - { - // Set bit 5 to M1 - o_addr |= ((mrnk & 0x01) << 58); - } - else - { - setRemainingRowBitsAndDimmSelect(5, row, rowBits, dslct, o_addr); - break; - } - - // Bit 4 - if (mstrs == 2 && slvs == 8) - { - // Set bit 4 to M1 - o_addr |= ((mrnk & 0x01) << 59); + uint64_t col = __reverseBits(i_addr.getCol(), 7); // C9 C8 C7 C6 C5 C4 C3 + uint64_t row = __reverseBits(i_addr.getRow(), 18); // R17 R16 R15 .. R1 R0 + uint64_t bnk = i_addr.getBank(); // BG0 BG1 B0 B1 B2 + uint64_t srnk = i_addr.getRank().getSlave(); // S0 S1 S2 + uint64_t mrnk = i_addr.getRank().getRankSlct(); // M0 M1 + uint64_t dslct = i_addr.getRank().getDimmSlct(); // D + + // Determine if a two DIMM config is used. Also, determine how many + // mrank (M0-M1), srnk (S0-S2), or extra row (R17-R15) bits are used. + bool twoDimmConfig; + uint8_t mrnkBits, srnkBits, extraRowBits; + o_rc = __getAddrConfig( i_chip, dslct, twoDimmConfig, mrnkBits, srnkBits, + extraRowBits ); + if ( SUCCESS != o_rc ) return o_rc; + + // Mask off the non-configured bits. If this address came from hardware, + // this would not be a problem. However, the get_mrank_range() and + // get_srank_range() HWPS got lazy just set the entire fields and did not + // take into account the actual bit ranges. + mrnk = __maskBits( mrnk, mrnkBits ); + srnk = __maskBits( srnk, srnkBits ); + row = __maskBits( row, 15 + extraRowBits ); + + // Combine master and slave ranks. + uint64_t rnk = (mrnk << srnkBits) | srnk; + uint8_t rnkBits = mrnkBits + srnkBits; + + // Now split the DIMM select and combined rank into components. + uint64_t rnk_pt1 = 0, rnk_pt2 = 0, rnk_pt3 = 0; + uint8_t rnkBits_pt1 = 0, rnkBits_pt2 = 0, rnkBits_pt3 = 0; + + if ( 0 == rnkBits ) + { + if ( twoDimmConfig ) // The DIMM select goes into part 3. + rnk_pt3 = dslct; rnkBits_pt3 = 1; + } + else // At least one master or slave. + { + // Put the LSB of the combined rank in part 3 and the rest in part 2. + rnk_pt3 = rnk & 0x1; rnkBits_pt3 = 1; + rnk_pt2 = rnk >> 1; rnkBits_pt2 = rnkBits - 1; - // Set remaining row bits - setRemainingRowBitsAndDimmSelect(3, row, rowBits, dslct, o_addr); - break; - } - else - { - setRemainingRowBitsAndDimmSelect(4, row, rowBits, dslct, o_addr); - break; - } + if ( twoDimmConfig ) // The DIMM select goes into part 1. + rnk_pt1 = dslct; rnkBits_pt1 = 1; + } - } while (0); + // Split the row into its components. + uint64_t r17_r15 = (row & 0x38000) >> 15; + uint64_t r14 = (row & 0x04000) >> 14; + uint64_t r13 = (row & 0x02000) >> 13; + uint64_t r12_r0 = (row & 0x01fff); + + // Split the column into its components. + uint64_t c9_c4 = (col & 0x7e) >> 1; + uint64_t c3 = (col & 0x01); + + // Split the bank into its components. + uint64_t bg0_bg1 = (bnk & 0x18) >> 3; + uint64_t b0 = (bnk & 0x04) >> 2; + uint64_t b1 = (bnk & 0x02) >> 1; + // NOTE: B2 is not supported on Nimbus. + + // Now start building the flexible part of the address (bits 0-7,23-33). + o_addr = (o_addr << rnkBits_pt1 ) | rnk_pt1; + o_addr = (o_addr << extraRowBits) | r17_r15; + o_addr = (o_addr << rnkBits_pt2 ) | rnk_pt2; + o_addr = (o_addr << 6 ) | c9_c4; + o_addr = (o_addr << 1 ) | b0; + o_addr = (o_addr << rnkBits_pt3 ) | rnk_pt3; + o_addr = (o_addr << 1 ) | b1; + o_addr = (o_addr << 2 ) | bg0_bg1; + o_addr = (o_addr << 1 ) | c3; + + // C2 is in bit 34, but the Nimbus physical address does not contain a C2. + // It will be set to 0 for now. Also, bits 35-39 are the rest of the cache + // line address, which we do not need. So, that will be set to 0 as well. + o_addr <<= 6; + + // Finally, insert R14,R12-R0,R13 into bits 8-22. + o_addr = ((o_addr & 0xfffffe0000ull) << 15) | (o_addr & 0x000001ffffull); + o_addr |= ((r14 << 14) | (r12_r0 << 1) | r13) << 17; return o_rc; + #undef PRDF_FUNC } @@ -314,15 +237,12 @@ int32_t getSystemAddr<TYPE_MCA>( ExtensibleChip * i_chip, MemAddr i_addr, int32_t l_rc = SUCCESS; do { - // Get 40-bit MCA Port address - l_rc = getMcaPortAddr( i_chip, i_addr, o_addr); + // Get the 40-bit port address (right justified). + l_rc = __getMcaPortAddr( i_chip, i_addr, o_addr ); if (l_rc) break; // Construct the 56-bit Powerbus address - // Shift the 40 bit port address in bits 0:39 over to bits 24:63 - o_addr = o_addr >> 24; - // Get MCA target position ExtensibleChip * mcs_chip = getConnectedParent( i_chip, TYPE_MCS ); uint8_t mcaPos = i_chip->getPos() % MAX_MCA_PER_MCS; @@ -479,7 +399,7 @@ int32_t page( ExtensibleChip * i_chip, MemAddr i_addr ) } sendPageGardRequest( sysAddr ); - PRDF_TRAC( PRDF_FUNC "Page dealloc address: 0x%016llX", sysAddr ); + PRDF_TRAC( PRDF_FUNC "Page dealloc address: 0x%016llx", sysAddr ); } while( 0 ); @@ -521,7 +441,7 @@ int32_t rank( ExtensibleChip * i_chip, MemRank i_rank ) // Send the address range to HV sendDynMemDeallocRequest( ssAddr, seAddr ); PRDF_TRAC( PRDF_FUNC "Rank dealloc for Start Addr: 0x%016llx " - "End Addr: 0x%016llX", ssAddr, seAddr ); + "End Addr: 0x%016llx", ssAddr, seAddr ); } while( 0 ); @@ -583,8 +503,8 @@ int32_t port( ExtensibleChip * i_chip ) // Send the address range to PHYP sendDynMemDeallocRequest( ssAddr, seAddr ); - PRDF_TRAC( PRDF_FUNC "MBA dealloc for Start Addr: 0x%016llx " - "End Addr: 0x%016llX", ssAddr, seAddr ); + PRDF_TRAC( PRDF_FUNC "Port dealloc for Start Addr: 0x%016llx " + "End Addr: 0x%016llx", ssAddr, seAddr ); } while (0); @@ -659,7 +579,7 @@ int32_t dimmSlct( TargetHandle_t i_dimm ) // Send the address range to PHYP sendDynMemDeallocRequest( smallestAddr, largestAddr ); PRDF_TRAC( PRDF_FUNC "DIMM Slct dealloc for Start Addr: 0x%016llx " - "End Addr: 0x%016llX", smallestAddr, largestAddr ); + "End Addr: 0x%016llx", smallestAddr, largestAddr ); } while (0); |