From 88105232544a3a358590336bc0b39d65bb5bed1e Mon Sep 17 00:00:00 2001 From: Prachi Gupta Date: Mon, 26 Jan 2015 13:28:58 -0600 Subject: SW274292: P8 Lab Alpine: memory map (opt_memmap procedure) update for Alpine Change-Id: I72c72a13683e3e707a9493a5499aa24d12090888 CQ:SW274292 Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/15304 Reviewed-by: Daniel M. Crowell Reviewed-by: Thi N. Tran Reviewed-by: PRACHI GUPTA Tested-by: PRACHI GUPTA Reviewed-on: http://gfw160.aus.stglabs.ibm.com:8080/gerrit/15316 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III --- .../hwpf/hwp/mc_config/mss_eff_config/opt_memmap.C | 907 ++++++++++++--------- .../mc_config/mss_eff_config/opt_memmap_errors.xml | 20 +- 2 files changed, 532 insertions(+), 395 deletions(-) (limited to 'src/usr/hwpf/hwp/mc_config') diff --git a/src/usr/hwpf/hwp/mc_config/mss_eff_config/opt_memmap.C b/src/usr/hwpf/hwp/mc_config/mss_eff_config/opt_memmap.C index 528b2baab..b7b170db3 100644 --- a/src/usr/hwpf/hwp/mc_config/mss_eff_config/opt_memmap.C +++ b/src/usr/hwpf/hwp/mc_config/mss_eff_config/opt_memmap.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2012,2014 */ +/* Contributors Listed Below - COPYRIGHT 2012,2015 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -22,7 +22,7 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ -// $Id: opt_memmap.C,v 1.20 2014/08/05 15:11:50 kahnevan Exp $ +// $Id: opt_memmap.C,v 1.21 2015/01/23 01:54:26 jmcgill Exp $ // $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ipl/fapi/opt_memmap.C,v $ @@ -36,58 +36,40 @@ // *! DESCRIPTION : Layout non-mirrored/mirrored address map (FAPI) // *! // *! OWNER NAME : Joe McGill Email: jmcgill@us.ibm.com -// *! BACKUP NAME : ??? Email: ???@us.ibm.com // *! //------------------------------------------------------------------------------ -//------------------------------------------------------------------------------ -// CHANGE HISTORY: -//------------------------------------------------------------------------------ -// Version:| Author: | Date: | Comment: -//---------|----------|---------|----------------------------------------------- -// 1.18 | jmcgill | 06/20/14| Add logic for flipped drawer enum -// 1.17 | dcrowell | 06/19/14| Switch from #define to attr for mirror origin -// 1.16 | jmcgill | 10/28/13| Offset drawers by 32TB rather than 1TB -// 1.15 | jmcgill | 09/17/13| Add logic to offset memory map based on -// | | | drawer number (required for multi-drawer -// | | | Brazos) -// 1.14 | thi | 08/29/13| Init variable to avoid HB compiler error. -// 1.13 | jmcgill | 08/29/13| Remove use of reverse iter (HB doesn't support) -// 1.12 | jmcgill | 07/10/13| Update to match new attributes, selective -// | | | aligment policy changes -// 1.11 | jmcgill | 06/11/13| Update for alternate BAR support (mirrored) -// 1.10 | jmcgill | 05/24/13| Updates for alternate BAR support -// 1.9 | jmcgill | 05/23/13| Address FW review issues -// 1.8 | jmcgill | 04/28/13| Add HTM/OCC memory allocation, fix namespace -// 1.7 | jmcgill | 04/20/13| Rewrite to add additional sorting capabilities -// | | | desired for exercisor mirroring testing -// 1.6 | vanlee | 02/22/13| Update sort logic of ProcBase class -// 1.5 | vanlee | 02/20/13| Add init paramter -// 1.4 | vanlee | 01/04/13| Added version string -// 1.1 | vanlee | 12/01/12| First drop -//------------------------------------------------------------------------------ - //------------------------------------------------------------------------------ // Design flow: // // opt_memmap() interacts with mss_eff_grouping() to define the assignment -// of non-mirrored/mirrored real address space on each chip in the drawer +// of non-mirrored/mirrored real address space on each chip in the drawer: +// - mss_eff_grouping() is responsible for the address assignment/layout +// of regions on a chip basis +// - opt_memmap() determines the final position of each chip's address +// space within the drawer +// +// Sequence: // // opt_memmap() will be called twice in the IPL flow, once before and once -// after mss_eff_grouping() +// after mss_eff_grouping(). // // 1) Call opt_memmap() with i_init = true -// - Each proc's ATTR_PROC_MEM_BASE attribute is set to 0 (512TB for flipped -// alignment) -// - Each proc's ATTR_PROC_MIRROR_BASE attribute is set to 512TB (0 for -// flipped alignment, 8TB for selective alignment) // -// This provides a basis for mss_eff_grouping() to stack all on-chip -// groups. -// -// NOTE: offset/mirrored origin (512TB above/below) is controlled by -// value of ATTR_MIRROR_BASE_ADDRESS +// opt_memmap() writes ATTR_PROC_[MEM|MIRROR]_BASE attributes to +// provide a basis for mss_eff_grouping() to stack all on-chip +// groups. Initially all chips are set to common values to provide +// a simple basis for size comparison. // +// non-mirrored mirrored +// mirror eff. stacking stacking stacking +// policy sort criteria origin origin +// -------- ------------- --------------------- ----------------------- +// NORMAL nm 0 TB X TB +// DRAWER nm 32 TB * drawer X TB+(32 TB * drawer)/2 +// FLIPPED m X TB 0 TB +// FLIPPED_DRAWER m X TB+(32 TB * drawer) 32TB * drawer +// // 2) mss_eff_grouping() call // - The HWP updates each proc's ATTR_PROC_[MEM|MIRROR]_[BASES|SIZES] // attributes based on the address regions allocated for installed memory @@ -96,27 +78,17 @@ // the stackable size of each on chip memory region // // 3) Call opt_memmap() with i_init = false -// - Consume mss_eff_grouping() attributes for each proc to determine +// - Consume mss_eff_grouping() *_ACK attributes for each proc to determine // "effective stackable" size of non-mirrored/mirrored regions // on each proc // - Stack procs based on their effective size and desired placement // policy -// non-mirrored mirrored -// mirror eff. stacking stacking stacking -// policy sort criteria origin origin -// -------- ------------- ------------ -------- -// NORMAL nm 0TB 512TB -// DRAWER nm 32TB*drawer 512TB+(32TB*drawer)/2 -// FLIPPED m 512TB 0TB -// FLIPPED_DRAWER m 512TB+(32TB*drawer) 32TB*drawer -// SELECTIVE nm+m 0TB 8TB -// // - Write ATTR_PROC_[MEM|MIRROR]_BASE attributes to their final // value // // 4) mss_eff_grouping() call // - Second run will produce properly aligned output attributes based -// on final per-chip base address attributes determine in prior step +// on final per-chip base address attributes determined in prior step // //------------------------------------------------------------------------------ @@ -141,42 +113,21 @@ using namespace fapi; //------------------------------------------------------------------------------ -// round to next largest power of 2 -inline uint64_t PowerOf2Roundedup(uint64_t i_number) -{ - if (i_number) - { - --i_number; - i_number |= i_number >> 1; - i_number |= i_number >> 2; - i_number |= i_number >> 4; - i_number |= i_number >> 8; - i_number |= i_number >> 16; - i_number |= i_number >> 32; - ++i_number; - } - return i_number; -} - - // class to represent memory region -// filled by attribute data from mss_eff_grouping procedure class MemRegion { - public: - // region type (mirrored/non-mirrored) - enum group_type { nm = 0, m = 1 }; + enum type { nm = 0, m = 1 }; - // region type - group_type iv_group_type; + // constructors + MemRegion(MemRegion::type type) : + iv_group_type(type), iv_base(0), iv_size(0) {} - // region parameters - uint64_t iv_base; - uint64_t iv_size; + MemRegion(MemRegion::type type, uint64_t base, uint64_t size) : + iv_group_type(type), iv_base(base), iv_size(size) {} - // comparison operator for sort + // comparison operators for sorting bool operator < (MemRegion rhs) const { bool l_lt = true; @@ -188,97 +139,101 @@ public: return l_lt; } - // constructor - MemRegion(MemRegion::group_type type, uint64_t base, uint64_t size) : - iv_group_type(type), iv_base(base), iv_size(size) {} + bool operator == (MemRegion rhs) const + { + return((iv_base == rhs.iv_base) && + (iv_size == rhs.iv_size)); + } + + bool operator > (MemRegion rhs) const + { + return (!(*this == rhs) && !(*this < rhs)); + } + + uint64_t getBase() const { return iv_base; } + uint64_t getSize() const { return iv_size; } + void setBase(uint64_t base) { iv_base = base; } + void setSize(uint64_t size) { iv_size = size; } + + // determine if region size is power of 2 aligned + bool isPowerOf2() const + { + return ((iv_size != 0) && !(iv_size & (iv_size - 1))); + } + + // round region size to next largest power of 2 + void roundNextPowerOf2() + { + iv_size = iv_size - 1; + iv_size = iv_size | (iv_size >> 1); + iv_size = iv_size | (iv_size >> 2); + iv_size = iv_size | (iv_size >> 4); + iv_size = iv_size | (iv_size >> 8); + iv_size = iv_size | (iv_size >> 16); + iv_size = iv_size | (iv_size >> 32); + iv_size = iv_size + 1; + } // debug function - void dump() + void dump() const { FAPI_DBG("Region [ %s ]", (iv_group_type == nm)?("nm"):("m")); - FAPI_DBG(" Base: %016llX", iv_base); - FAPI_DBG(" Size: %016llX", iv_size); + FAPI_DBG(" Base: 0x%016llX", iv_base); + FAPI_DBG(" Size: 0x%016llX", iv_size); } + +private: + // region type + type iv_group_type; + + // region parameters + uint64_t iv_base; + uint64_t iv_size; + }; -// class to represent memory map (non-mirrored/mirrored) on one processor chip +// class to represent memory map (non-mirrored/mirrored regions) on one processor chip class ProcChipMemmap { - public: - // pointer to processor chip target - Target *iv_target; - // mirroring policy - uint8_t iv_mirror_policy; - - // chip location information - uint8_t iv_pos; - uint8_t iv_node_id; - uint8_t iv_chip_id; - - // chip non-mirrored base, effective size, and member regions - uint64_t iv_nm_base; - uint64_t iv_nm_eff_size; - std::vector iv_nm_regions; - - // chip mirrored base, effective size, and member regions - uint64_t iv_m_base; - uint64_t iv_m_eff_size; - std::vector iv_m_regions; + // constructor + ProcChipMemmap(Target* t, MemRegion::type sort, bool chip_as_group) : + iv_target(t), iv_sort(sort), iv_chip_as_group(chip_as_group), iv_node_id(0), iv_chip_id(0), iv_nm(MemRegion::nm), iv_m(MemRegion::m) {} // comparison operator for sort - // sort in increasing size, and decreasing proc position + // sort in increasing effective size, and decreasing proc position // e.g. proc0 and proc2 have same size, then the order will be // proc2 then proc0 bool operator < (ProcChipMemmap rhs) const { + uint8_t l_pos = ((4*iv_node_id)+iv_chip_id); + uint8_t r_pos = ((4*rhs.iv_node_id)+rhs.iv_chip_id); + bool l_lt = true; - uint64_t l_this_eff_size = 0; - uint64_t l_rhs_eff_size = 0; - - // compute effective size based on mirror policy - // sort by non-mirrored size - if (((iv_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_NORMAL) && - (rhs.iv_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_NORMAL)) || - ((iv_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_DRAWER) && - (rhs.iv_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_DRAWER)) || - ((iv_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_SELECTIVE) && - (rhs.iv_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_SELECTIVE))) - { - l_this_eff_size = iv_nm_eff_size; - l_rhs_eff_size = rhs.iv_nm_eff_size; - } - // sort by mirrored size - else if (((iv_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_FLIPPED) && - (rhs.iv_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_FLIPPED)) || - ((iv_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_FLIPPED_DRAWER) && - (rhs.iv_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_FLIPPED_DRAWER))) - { - l_this_eff_size = iv_m_eff_size; - l_rhs_eff_size = rhs.iv_m_eff_size; - } // perform sort comparison - if (l_this_eff_size > l_rhs_eff_size || - (l_this_eff_size == l_rhs_eff_size && iv_pos < rhs.iv_pos)) + MemRegion l = ((iv_sort == MemRegion::nm)?(iv_nm):(iv_m)); + MemRegion r = ((iv_sort == MemRegion::nm)?(rhs.iv_nm):(rhs.iv_m)); + if ((l > r) || + ((l == r) && (l_pos < r_pos))) { l_lt = false; } return l_lt; } - // constructor - ProcChipMemmap(Target* t, uint8_t mirror_policy) : - iv_target(t), iv_mirror_policy(mirror_policy) {} - // process chip data from attributes ReturnCode processAttributes() { ReturnCode rc; - uint64_t l_nm_bases[OPT_MEMMAP_MAX_NM_REGIONS]; - uint64_t l_nm_sizes[OPT_MEMMAP_MAX_NM_REGIONS]; - uint64_t l_m_bases[OPT_MEMMAP_MAX_M_REGIONS]; - uint64_t l_m_sizes[OPT_MEMMAP_MAX_M_REGIONS]; + uint64_t l_nm_base; + uint64_t l_m_base; + uint64_t l_nm_bases[OPT_MEMMAP_MAX_NM_REGIONS] = { 0 }; + uint64_t l_nm_sizes[OPT_MEMMAP_MAX_NM_REGIONS] = { 0 }; + uint64_t l_m_bases[OPT_MEMMAP_MAX_M_REGIONS] = { 0 }; + uint64_t l_m_sizes[OPT_MEMMAP_MAX_M_REGIONS] = { 0 }; + std::vector l_nm_regions; + std::vector l_m_regions; do { @@ -300,26 +255,27 @@ public: FAPI_ERR("Error from FAPI_ATTR_GET (ATTR_FABRIC_CHIP)"); break; } - iv_pos = ((4*iv_node_id)+iv_chip_id); - // retrieve base address for each chip + // retrieve base address attributes (computed by prior opt_memmap call) rc = FAPI_ATTR_GET(ATTR_PROC_MEM_BASE, iv_target, - iv_nm_base); + l_nm_base); if (!rc.ok()) { FAPI_ERR("Error from FAPI_ATTR_GET (ATTR_PROC_MEM_BASE)"); break; } + iv_nm.setBase(l_nm_base); rc = FAPI_ATTR_GET(ATTR_PROC_MIRROR_BASE, iv_target, - iv_m_base); + l_m_base); if (!rc.ok()) { FAPI_ERR("Error from FAPI_ATTR_GET (ATTR_PROC_MIRROR_BASE)"); break; } + iv_m.setBase(l_m_base); // retrieve regions (bases and sizes) computed by mss_eff_grouping rc = FAPI_ATTR_GET(ATTR_PROC_MEM_BASES_ACK, @@ -330,7 +286,7 @@ public: FAPI_ERR("Error from FAPI_ATTR_GET (ATTR_PROC_MEM_BASES_ACK)"); break; } - + rc = FAPI_ATTR_GET(ATTR_PROC_MEM_SIZES_ACK, iv_target, l_nm_sizes); @@ -347,7 +303,7 @@ public: FAPI_ERR("Error from FAPI_ATTR_GET (ATTR_PROC_MIRROR_BASES_ACK)"); break; } - + rc = FAPI_ATTR_GET(ATTR_PROC_MIRROR_SIZES_ACK, iv_target, l_m_sizes); @@ -358,15 +314,15 @@ public: } // populate non-mirrored regions - FAPI_INF("Chip n%d:p%d", iv_node_id, iv_chip_id); + FAPI_INF("Process Chip n%d:p%d: Begin", iv_node_id, iv_chip_id); for (uint8_t i = 0; i < OPT_MEMMAP_MAX_NM_REGIONS; i++) { if (l_nm_sizes[i] != 0) { - FAPI_INF(" l_nm_bases[%d] = %016llX", i, l_nm_bases[i]); - FAPI_INF(" l_nm_sizes[%d] = %016llX", i, l_nm_sizes[i]); + FAPI_INF(" nm_bases[%d] = 0x%016llX", i, l_nm_bases[i]); + FAPI_INF(" nm_sizes[%d] = 0x%016llX", i, l_nm_sizes[i]); MemRegion r(MemRegion::nm, l_nm_bases[i], l_nm_sizes[i]); - iv_nm_regions.push_back(r); + l_nm_regions.push_back(r); } } @@ -376,92 +332,117 @@ public: if (l_m_sizes[i] != 0) { // align to common origin - FAPI_INF(" l_m_bases[%d] = %016llX", i, l_m_bases[i]); - FAPI_INF(" l_m_sizes[%d] = %016llX", i, l_m_sizes[i]); + FAPI_INF(" m_bases[%d] = 0x%016llX", i, l_m_bases[i]); + FAPI_INF(" m_sizes[%d] = 0x%016llX", i, l_m_sizes[i]); MemRegion r(MemRegion::m, l_m_bases[i], l_m_sizes[i]); - iv_m_regions.push_back(r); + l_m_regions.push_back(r); } } // sort regions for effective size calculations - std::sort(iv_nm_regions.begin(), iv_nm_regions.end()); - std::sort(iv_m_regions.begin(), iv_m_regions.end()); + std::sort(l_nm_regions.begin(), l_nm_regions.end()); + std::sort(l_m_regions.begin(), l_m_regions.end()); - // compute effective size of chip address space - // this is simply the end address of the last region in + // compute effective size of chip address space associated with // each stack (rounded up to a power of 2) - if (iv_nm_regions.size() != 0) + if (l_nm_regions.size() != 0) { - if (iv_nm_base != iv_nm_regions[0].iv_base) +// if (iv_nm.getBase() != l_nm_regions[0].getBase()) +// { +// const uint64_t& ADDR = iv_nm.getBase(); +// FAPI_ERR("Unexpected value returned for ATTR_PROC_MEM_BASE (='0x%016llX')", +// iv_nm.getBase()); +// FAPI_SET_HWP_ERROR(rc, RC_OPT_MEMMAP_MEM_BASE_ERR); +// break; +// } + + iv_nm.setSize(l_nm_regions[l_nm_regions.size()-1].getBase() - + l_nm_regions[0].getBase() + + l_nm_regions[l_nm_regions.size()-1].getSize()); + if (!iv_nm.isPowerOf2()) { - const uint64_t& ADDR = iv_nm_base; - FAPI_ERR("Unexpected value returned for ATTR_PROC_MEM_BASE (=%016llX)", - iv_nm_base); - FAPI_SET_HWP_ERROR(rc, RC_OPT_MEMMAP_MEM_BASE_ERR); - break; + iv_nm.roundNextPowerOf2(); } - - iv_nm_eff_size = iv_nm_regions[iv_nm_regions.size()-1].iv_base - - iv_nm_regions[0].iv_base; - iv_nm_eff_size += iv_nm_regions[iv_nm_regions.size()-1].iv_size; - iv_nm_eff_size = PowerOf2Roundedup(iv_nm_eff_size); } else { - iv_nm_eff_size = 0; + iv_nm.setSize(0); } - FAPI_INF(" nm_eff_size = %016llX", iv_nm_eff_size); + FAPI_INF(" nm_eff_size = 0x%016llX", iv_nm.getSize()); - if (iv_m_regions.size() != 0) + if (l_m_regions.size() != 0) { - if (iv_m_base != iv_m_regions[0].iv_base) +// if (iv_m.getBase() != l_m_regions[0].getBase()) +// { +// const uint64_t& ADDR = iv_m.getBase(); +// FAPI_ERR("Unexpected value returned for ATTR_PROC_MIRROR_BASE (='0x%016llX')", +// iv_m.getBase()); +// FAPI_SET_HWP_ERROR(rc, RC_OPT_MEMMAP_MIRROR_BASE_ERR); +// break; +// } + + iv_m.setSize(l_m_regions[l_m_regions.size()-1].getBase() - + l_m_regions[0].getBase() + + l_m_regions[l_m_regions.size()-1].getSize()); + if (!iv_m.isPowerOf2()) { - const uint64_t& ADDR = iv_m_base; - FAPI_ERR("Unexpected value returned for ATTR_PROC_MIRROR_BASE (=%016llX)", - iv_m_base); - FAPI_SET_HWP_ERROR(rc, RC_OPT_MEMMAP_MIRROR_BASE_ERR); - break; + iv_m.roundNextPowerOf2(); } - - iv_m_eff_size = iv_m_regions[iv_m_regions.size()-1].iv_base - - iv_m_regions[0].iv_base; - iv_m_eff_size += iv_m_regions[iv_m_regions.size()-1].iv_size; - iv_m_eff_size = PowerOf2Roundedup(iv_m_eff_size); } else { - iv_m_eff_size = 0; + iv_m.setSize(0); } - FAPI_INF(" m_eff_size = %016llX", iv_m_eff_size); + FAPI_INF(" m_eff_size = 0x%016llX", iv_m.getSize()); + FAPI_INF("Process Chip: End"); } while(0); return rc; } - // establish new non-mirrored base address for this chip - void setNMBase(const uint64_t& base) + // return group ID + uint8_t getGroupID() const { - iv_nm_base = base; + uint8_t pos = ((4*iv_node_id)+iv_chip_id); + return((iv_chip_as_group)?(pos):(iv_node_id)); } - // establish new mirrored base address for this chip - void setMBase(const uint64_t& base) + // return specified region size + uint64_t getSize(const MemRegion::type type) const { - iv_m_base = base; + return((type == MemRegion::nm)?(iv_nm.getSize()):(iv_m.getSize())); + } + + // establish new base address for this chip + void setBase(const MemRegion::type type, const uint64_t& base) + { + if (type == MemRegion::nm) + { + iv_nm.setBase(base); + } + else + { + iv_m.setBase(base); + } } // flush state back to attributes ReturnCode flushAttributes() { ReturnCode rc; + uint64_t nm_base = iv_nm.getBase(); + uint64_t m_base = iv_m.getBase(); + FAPI_INF("Stack Chip n%d:p%d: Begin", iv_node_id, iv_chip_id); + FAPI_INF(" nm_base: 0x%016llX", nm_base); + FAPI_INF(" m_base: 0x%016llX", m_base); do { // set base addresses rc = FAPI_ATTR_SET(ATTR_PROC_MEM_BASE, iv_target, - iv_nm_base); + nm_base); if (!rc.ok()) { FAPI_ERR("Error from FAPI_ATTR_SET (ATTR_PROC_MEM_BASE)"); @@ -470,7 +451,7 @@ public: rc = FAPI_ATTR_SET(ATTR_PROC_MIRROR_BASE, iv_target, - iv_m_base); + m_base); if (!rc.ok()) { FAPI_ERR("Error from FAPI_ATTR_SET (ATTR_PROC_MIRROR_BASE)"); @@ -478,258 +459,400 @@ public: } } while(0); + FAPI_INF("Stack Chip: End"); return rc; } + +private: + // pointer to processor chip target + Target *iv_target; + // sort criteria + MemRegion::type iv_sort; + // chip position information + bool iv_chip_as_group; + uint8_t iv_node_id; + uint8_t iv_chip_id; + // chip effective non-mirrored region + MemRegion iv_nm; + // chip effective mirrored region + MemRegion iv_m; }; -ReturnCode opt_memmap(std::vector & i_procs, bool i_init) +// class to represent group in drawer memory map +class ProcGroupMemmap { - ReturnCode rc; - std::vector l_drawer_memmap; - uint8_t l_mirror_policy; +public: + // constructor + ProcGroupMemmap(uint8_t group_id, uint8_t mirror_policy, MemRegion::type sort) : + iv_group_id(group_id), iv_mirror_policy(mirror_policy), iv_sort(sort), iv_nm(MemRegion::nm), iv_m(MemRegion::m) {} - do + // comparison operator for sort + // sort in increasing size, and decreasing node ID + // e.g. group2 and group0 have same size, then the order will be + // group2 then group0 + bool operator < (const ProcGroupMemmap & rhs) const { - // retrieve mirroring placement policy attribute - rc = FAPI_ATTR_GET(ATTR_MEM_MIRROR_PLACEMENT_POLICY, - NULL, - l_mirror_policy); - if (!rc.ok()) + bool l_lt = true; + // perform sort comparison + MemRegion l = ((iv_sort == MemRegion::nm)?(iv_nm):(iv_m)); + MemRegion r = ((iv_sort == MemRegion::nm)?(rhs.iv_nm):(rhs.iv_m)); + if ((l > r) || + ((l == r) && (iv_group_id < rhs.iv_group_id))) { - FAPI_ERR("Error querying ATTR_MEM_MIRROR_PLACEMENT_POLICY"); - break; + l_lt = false; } + return l_lt; + } - uint64_t l_mirror_origin = 0; - rc = FAPI_ATTR_GET(ATTR_MIRROR_BASE_ADDRESS, - NULL, - l_mirror_origin); - if (!rc.ok()) + // retreive group ID + uint8_t getGroupID() const { return iv_group_id; } + + // add chip to group + void addChip(const ProcChipMemmap & chip) + { + iv_nm.setSize(iv_nm.getSize() + chip.getSize(MemRegion::nm)); + iv_m.setSize(iv_m.getSize() + chip.getSize(MemRegion::m)); + iv_chips.push_back(chip); + } + + // finalize effective group size + void processGroup() + { + FAPI_INF("Process Group %d: Begin", iv_group_id); + // sort member chips based on their effective stackable sizes + // individual chip sizes should already be power-of-2 aligned + std::sort(iv_chips.begin(), iv_chips.end()); + + // ensure size is rounded to power-of-2 + if (!iv_nm.isPowerOf2()) { - FAPI_ERR("Error querying ATTR_MIRROR_BASE_ADDRESS"); - break; + iv_nm.roundNextPowerOf2(); + } + if (!iv_m.isPowerOf2()) + { + iv_m.roundNextPowerOf2(); } + FAPI_INF(" nm_eff_size = 0x%016llX", iv_nm.getSize()); + FAPI_INF(" m_eff_size = 0x%016llX", iv_m.getSize()); + FAPI_INF("Process Group: End"); + } - FAPI_INF("opt_memmap called with i_init: %d, mirror_policy: %d, mirror_origin: %016llX", - (i_init)?(1):(0), l_mirror_policy, l_mirror_origin); + // return specified region size + uint64_t getSize(const MemRegion::type type) const + { + return((type == MemRegion::nm)?(iv_nm.getSize()):(iv_m.getSize())); + } - // first pass of execution - if (i_init) - { - uint64_t mem_base; - uint64_t mirror_base; + // walk through member chips, from largest->smallest effective size + // assign base addresses for each + ReturnCode stackChips(uint64_t nm_base, uint64_t m_base) + { + ReturnCode rc; + uint64_t l_nm_base_curr = nm_base; + uint64_t l_m_base_curr = m_base; + + iv_nm.setBase(nm_base); + iv_m.setBase(m_base); - if (l_mirror_policy == - ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_NORMAL) + FAPI_INF("Stack Group %d: Begin", iv_group_id); + for (uint8_t i = iv_chips.size(); + i != 0; + --i) + { + // establish base addresses for each chip & realign + // all groups on this chip to reflect this + iv_chips[i-1].setBase(MemRegion::nm, l_nm_base_curr); + iv_chips[i-1].setBase(MemRegion::m, l_m_base_curr); + l_nm_base_curr += iv_chips[i-1].getSize(MemRegion::nm); + + if ((iv_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_NORMAL) || + (iv_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_DRAWER)) { - mem_base = OPT_MEMMAP_BASE_ORIGIN; - mirror_base = l_mirror_origin; + l_m_base_curr += iv_chips[i-1].getSize(MemRegion::nm) / 2; } - else if (l_mirror_policy == - ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_FLIPPED) + else { - mem_base = l_mirror_origin; - mirror_base = OPT_MEMMAP_BASE_ORIGIN; + l_m_base_curr += iv_chips[i-1].getSize(MemRegion::m); } - else if (l_mirror_policy == - ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_SELECTIVE) + + // flush attributes for this chip + rc = iv_chips[i-1].flushAttributes(); + if (!rc.ok()) { - mem_base = OPT_MEMMAP_BASE_ORIGIN; - mirror_base = OPT_MEMMAP_SELECTIVE_ORIGIN; + FAPI_ERR("Error from flushAttributes"); + break; } + } - // loop across all chips in drawer, set common - // base for non-mirrored/mirrored memory on each chip in preparation - // for mss_eff_grouping call - for (std::vector::iterator l_iter = i_procs.begin(); - l_iter != i_procs.end(); - ++l_iter) - { - if ((l_iter == i_procs.begin()) && - ((l_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_DRAWER) || - (l_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_FLIPPED_DRAWER))) - { - uint8_t drawer_id; - rc = FAPI_ATTR_GET(ATTR_FABRIC_NODE_ID, - &(*l_iter), - drawer_id); - if (!rc.ok()) - { - FAPI_ERR("Error from FAPI_ATTR_GET (ATTR_FABRIC_NODE_ID)"); - break; - } - - if (l_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_DRAWER) - { - mem_base = drawer_id * 32 * OPT_MEMMAP_TB; - mirror_base = l_mirror_origin + (mem_base / 2); - } - else - { - mirror_base = drawer_id * 32 * OPT_MEMMAP_TB; - mem_base = l_mirror_origin + mirror_base; - } - } + FAPI_INF("Stack Group: End"); + return rc; + } - rc = FAPI_ATTR_SET(ATTR_PROC_MEM_BASE, - &(*l_iter), - mem_base); - if (!rc.ok()) - { - FAPI_ERR("Error from FAPI_ATTR_SET (ATTR_PROC_MEM_BASE)!"); - break; - } +private: + // collection of member chips + std::vector iv_chips; + // group ID + uint8_t iv_group_id; + // mirroring policy/sort criteria + uint8_t iv_mirror_policy; + MemRegion::type iv_sort; + // effective sizes + MemRegion iv_nm; + MemRegion iv_m; - rc = FAPI_ATTR_SET(ATTR_PROC_MIRROR_BASE, - &(*l_iter), - mirror_base); - if (!rc.ok()) - { - FAPI_ERR("Error from FAPI_ATTR_SET (ATTR_PROC_MIRROR_BASE)!"); - break; - } - } - if (!rc.ok()) +}; + + +// class to represent memory map at drawer scope +class ProcDrawerMemmap +{ + +public: + // constructor + ProcDrawerMemmap(uint8_t mirror_policy, uint8_t group_policy, uint64_t alt_origin, uint8_t drawer_id) : + iv_mirror_policy(mirror_policy), iv_group_policy(group_policy), iv_alt_origin(alt_origin), iv_drawer_id(drawer_id) + { + // establish base address values based on memory map policy + if ((iv_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_NORMAL) || + (iv_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_DRAWER)) + { + iv_sort_policy = MemRegion::nm; + iv_nm_base = OPT_MEMMAP_BASE_ORIGIN + (iv_drawer_id * 32 * OPT_MEMMAP_TB); + iv_m_base = iv_alt_origin + (iv_nm_base / 2); + } + else if ((iv_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_FLIPPED) || + (iv_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_FLIPPED_DRAWER)) + { + iv_sort_policy = MemRegion::m; + iv_m_base = OPT_MEMMAP_BASE_ORIGIN + (iv_drawer_id * 32 * OPT_MEMMAP_TB); + iv_nm_base = iv_alt_origin + iv_m_base; + + } + } + + // return drawer sort/ordering policies + MemRegion::type getSortPolicy() const { return iv_sort_policy; } + bool getGroupPolicy() const { return (iv_group_policy == ENUM_ATTR_OPT_MEMMAP_GROUP_POLICY_CHIP_AS_GROUP); } + + uint64_t getBase(MemRegion::type type) + { + if (type == MemRegion::nm) { return iv_nm_base; } + else { return iv_m_base; } + } + + // chip processing function + ReturnCode insertChip(ProcChipMemmap chip) + { + ReturnCode rc; + + // search for matching group + uint8_t group_match_count = 0; + for (std::vector::iterator g = iv_groups.begin(); + g != iv_groups.end(); + g++) + { + // add to existing group + if (chip.getGroupID() == g->getGroupID()) { - break; + g->addChip(chip); + group_match_count++; } } - // second pass of execution - // reorder chips based on their effective stackable size - else + // create group if no matches found + if (group_match_count == 0) { - // base for alignment of mirrored/non-mirrored regions - uint64_t l_m_base_curr = 0; - uint64_t l_nm_base_curr = 0; + ProcGroupMemmap new_group(chip.getGroupID(), iv_mirror_policy, iv_sort_policy); + new_group.addChip(chip); + iv_groups.push_back(new_group); + } + // multiple group matches were found, error + else if (group_match_count != 1) + { + const uint8_t& GROUP_ID = chip.getGroupID(); + const uint8_t& MATCH_COUNT = group_match_count; + FAPI_ERR("Internal error, chip matched multiple group IDs (=%d)", + chip.getGroupID()); + FAPI_SET_HWP_ERROR(rc, RC_OPT_MEMMAP_GROUP_ERR); + } + return rc; + } + + // drawer processing function + ReturnCode processDrawer() + { + ReturnCode rc; + FAPI_INF("Process Drawer: Begin"); - if (l_mirror_policy == - ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_NORMAL) + // determine effective size of each group + for (std::vector::iterator g = iv_groups.begin(); + g != iv_groups.end(); + g++) + { + g->processGroup(); + } + + // order groups by effective size + std::sort(iv_groups.begin(), iv_groups.end()); + + FAPI_INF("Stack Drawer: Begin"); + // walk through groups, from largest->smallest effective size + for (uint8_t i = iv_groups.size(); + i != 0; + --i) + { + // establish base addresses for group + rc = iv_groups[i-1].stackChips(iv_nm_base, iv_m_base); + if (!rc.ok()) { - // non-mirrored at zero, mirrored at offset - l_nm_base_curr = OPT_MEMMAP_BASE_ORIGIN; - l_m_base_curr = l_mirror_origin; + break; } - else if (l_mirror_policy == - ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_FLIPPED) + + // establish base addresses for next group + iv_nm_base += iv_groups[i-1].getSize(MemRegion::nm); + if ((iv_mirror_policy == + ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_NORMAL) || + (iv_mirror_policy == + ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_DRAWER)) { - // mirrored at zero, non-mirrored at offset - l_nm_base_curr = l_mirror_origin; - l_m_base_curr = OPT_MEMMAP_BASE_ORIGIN; + iv_m_base += iv_groups[i-1].getSize(MemRegion::nm) / 2; } - else if (l_mirror_policy == - ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_SELECTIVE) + else { - l_nm_base_curr = OPT_MEMMAP_BASE_ORIGIN; - l_m_base_curr = OPT_MEMMAP_SELECTIVE_ORIGIN; + iv_m_base += iv_groups[i-1].getSize(MemRegion::m); } + } - // loop across all chips in drawer, consume results of - // mss_eff_grouping call - for (std::vector::iterator l_iter = i_procs.begin(); - l_iter != i_procs.end(); - ++l_iter) - { - if ((l_iter == i_procs.begin()) && - ((l_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_DRAWER) || - (l_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_FLIPPED_DRAWER))) - { - uint8_t drawer_id; - rc = FAPI_ATTR_GET(ATTR_FABRIC_NODE_ID, - &(*l_iter), - drawer_id); - if (!rc.ok()) - { - FAPI_ERR("Error from FAPI_ATTR_GET (ATTR_FABRIC_NODE_ID)"); - break; - } - - if (l_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_DRAWER) - { - l_nm_base_curr = drawer_id * 32 * OPT_MEMMAP_TB; - l_m_base_curr = l_mirror_origin + (l_nm_base_curr / 2); - } - else - { - l_m_base_curr = drawer_id * 32 * OPT_MEMMAP_TB; - l_nm_base_curr = l_mirror_origin + l_m_base_curr; - } - } + FAPI_INF("Stack Drawer: End"); + FAPI_INF("Process Drawer: End"); + return rc; + } - ProcChipMemmap p(&(*l_iter), l_mirror_policy); - rc = p.processAttributes(); - if (!rc.ok()) - { - FAPI_ERR("Error from processAttributes"); - break; - } - l_drawer_memmap.push_back(p); - } +private: + // collection of member groups + std::vector iv_groups; + + // mirror policy + uint8_t iv_mirror_policy; + uint8_t iv_group_policy; + MemRegion::type iv_sort_policy; + uint64_t iv_alt_origin; + uint8_t iv_drawer_id; + + // current base address values + uint64_t iv_nm_base; + uint64_t iv_m_base; + +}; + + +// HWP entry point +ReturnCode opt_memmap(std::vector & i_procs, bool i_init) +{ + ReturnCode rc; + uint8_t l_mirror_policy; + uint8_t l_group_policy; + uint64_t l_alt_origin; + uint8_t l_drawer_id = 0; + + do + { + // retrieve mirroring policy/placement attributes + rc = FAPI_ATTR_GET(ATTR_MEM_MIRROR_PLACEMENT_POLICY, + NULL, + l_mirror_policy); + if (!rc.ok()) + { + FAPI_ERR("Error querying ATTR_MEM_MIRROR_PLACEMENT_POLICY"); + break; + } + + rc = FAPI_ATTR_GET(ATTR_OPT_MEMMAP_GROUP_POLICY, + NULL, + l_group_policy); + if (!rc.ok()) + { + FAPI_ERR("Error querying ATTR_OPT_MEMMAP_GROUP_POLICY"); + break; + } + + rc = FAPI_ATTR_GET(ATTR_MIRROR_BASE_ADDRESS, + NULL, + l_alt_origin); + if (!rc.ok()) + { + FAPI_ERR("Error querying ATTR_MIRROR_BASE_ADDRESS"); + break; + } + + // all chips in input vector must lie in same drawer + // if required by placement policy, determine drawer number + // (equivalent to the fabric node ID) + if ((l_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_DRAWER) || + (l_mirror_policy == ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_FLIPPED_DRAWER)) + { + rc = FAPI_ATTR_GET(ATTR_FABRIC_NODE_ID, + &(*(i_procs.begin())), + l_drawer_id); if (!rc.ok()) { + FAPI_ERR("Error from FAPI_ATTR_GET (ATTR_FABRIC_NODE_ID)"); break; } + } - // sort chips based on their effective stackable size - std::sort(l_drawer_memmap.begin(), l_drawer_memmap.end()); + FAPI_INF("opt_memmap called with i_init: %d, mirror_policy: %d, group_policy: %d, alternate_origin: 0x%016llX", + (i_init)?(1):(0), l_mirror_policy, l_group_policy, l_alt_origin); - // walk through chips, from largest->smallest effective size & - // assign base addresses for each group - for (uint8_t i = l_drawer_memmap.size(); - i != 0; - --i) - { - FAPI_DBG("Stacking chip n%d:p%d (eff nm size = %lld GB, eff m size = %lld GB)...", - l_drawer_memmap[i-1].iv_node_id, - l_drawer_memmap[i-1].iv_chip_id, - l_drawer_memmap[i-1].iv_nm_eff_size / OPT_MEMMAP_GB, - l_drawer_memmap[i-1].iv_m_eff_size / OPT_MEMMAP_GB); - - if (l_mirror_policy == - ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_SELECTIVE) - { - l_m_base_curr += l_drawer_memmap[i-1].iv_nm_eff_size; - } + // construct drawer memory map object + ProcDrawerMemmap l_drawer(l_mirror_policy, l_group_policy, l_alt_origin, l_drawer_id); - // establish base addresses for this chip & realign - // all groups on this chip to reflect this - l_drawer_memmap[i-1].setNMBase(l_nm_base_curr); - l_drawer_memmap[i-1].setMBase(l_m_base_curr); - FAPI_DBG("nm base: %016llX", l_nm_base_curr); - FAPI_DBG("m base: %016llX", l_m_base_curr); - if ((l_mirror_policy == - ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_NORMAL) || - (l_mirror_policy == - ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_DRAWER)) - { - l_nm_base_curr += l_drawer_memmap[i-1].iv_nm_eff_size; - l_m_base_curr += l_drawer_memmap[i-1].iv_nm_eff_size / 2; - } - else if ((l_mirror_policy == - ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_FLIPPED) || - (l_mirror_policy == - ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_FLIPPED_DRAWER)) + // process all chips in scope of drawer + for (std::vector::iterator l_iter = i_procs.begin(); + l_iter != i_procs.end(); + l_iter++) + { + ProcChipMemmap l_chip(&(*l_iter), l_drawer.getSortPolicy(), l_drawer.getGroupPolicy()); + + if (i_init) + { + l_chip.setBase(MemRegion::nm, l_drawer.getBase(MemRegion::nm)); + l_chip.setBase(MemRegion::m, l_drawer.getBase(MemRegion::m)); + rc = l_chip.flushAttributes(); + if (!rc.ok()) { - l_nm_base_curr += l_drawer_memmap[i-1].iv_nm_eff_size; - l_m_base_curr += l_drawer_memmap[i-1].iv_m_eff_size; + FAPI_ERR("Error from flushAttributes"); + break; } - else if (l_mirror_policy == - ENUM_ATTR_MEM_MIRROR_PLACEMENT_POLICY_SELECTIVE) + } + else + { + rc = l_chip.processAttributes(); + if (!rc.ok()) { - l_nm_base_curr += l_drawer_memmap[i-1].iv_nm_eff_size; - l_m_base_curr += l_drawer_memmap[i-1].iv_nm_eff_size / 2; + FAPI_ERR("Error from processAttributes"); + break; } - - // flush attributes for this chip - rc = l_drawer_memmap[i-1].flushAttributes(); + rc = l_drawer.insertChip(l_chip); if (!rc.ok()) { - FAPI_ERR("Error from flushAttributes"); + FAPI_ERR("Error from insertChip"); break; } } + } + if (!rc.ok()) + { + break; + } + + // process drawer to align each group & its member chips + if (!i_init) + { + rc = l_drawer.processDrawer(); if (!rc.ok()) { + FAPI_ERR("Error from processDrawer"); break; } } diff --git a/src/usr/hwpf/hwp/mc_config/mss_eff_config/opt_memmap_errors.xml b/src/usr/hwpf/hwp/mc_config/mss_eff_config/opt_memmap_errors.xml index b22e4d66f..9ac15fca1 100644 --- a/src/usr/hwpf/hwp/mc_config/mss_eff_config/opt_memmap_errors.xml +++ b/src/usr/hwpf/hwp/mc_config/mss_eff_config/opt_memmap_errors.xml @@ -5,7 +5,9 @@ - + + + @@ -20,7 +22,7 @@ - + @@ -33,7 +35,7 @@ HIGH - + RC_OPT_MEMMAP_MIRROR_BASE_ERR Unexpected value for ATTR_PROC_MIRROR_BASE returned after mss_eff_grouping execution. @@ -43,4 +45,16 @@ HIGH + + + RC_OPT_MEMMAP_GROUP_ERR + Internal error, chip matched multiple Group IDs. + GROUP_ID + MATCH_COUNT + + CODE + HIGH + + + -- cgit v1.2.1