diff options
-rw-r--r-- | src/include/kernel/cpumgr.H | 3 | ||||
-rw-r--r-- | src/include/sys/misc.h | 7 | ||||
-rw-r--r-- | src/include/sys/mmio.h | 3 | ||||
-rw-r--r-- | src/kernel/cpumgr.C | 8 | ||||
-rw-r--r-- | src/kernel/syscall.C | 5 | ||||
-rw-r--r-- | src/lib/syscall_misc.C | 8 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/build_winkle_images/build_winkle_images.C | 11 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/core_activate/core_activate.C | 10 | ||||
-rw-r--r-- | src/usr/hwpf/hwp/thread_activate/thread_activate.C | 15 | ||||
-rw-r--r-- | src/usr/intr/intrrp.C | 66 | ||||
-rw-r--r-- | src/usr/intr/test/intrtest.H | 13 | ||||
-rw-r--r-- | src/usr/targeting/common/xmltohb/attribute_types.xml | 15 | ||||
-rw-r--r-- | src/usr/targeting/common/xmltohb/target_types.xml | 5 |
13 files changed, 150 insertions, 19 deletions
diff --git a/src/include/kernel/cpumgr.H b/src/include/kernel/cpumgr.H index 264583b5f..23207bf11 100644 --- a/src/include/kernel/cpumgr.H +++ b/src/include/kernel/cpumgr.H @@ -135,8 +135,9 @@ class CpuManager * Create structures to support a core activating and start the core. * * @param[in] pir - PIR value of first thread in core. + * @param[in] i_threads - Bitstring of threads to enable (left-justified). */ - static int startCore(uint64_t pir); + static int startCore(uint64_t pir,uint64_t i_threads); /** @fn forceMemoryPeriodic() diff --git a/src/include/sys/misc.h b/src/include/sys/misc.h index c8d3ba510..8c119aca5 100644 --- a/src/include/sys/misc.h +++ b/src/include/sys/misc.h @@ -5,7 +5,7 @@ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2011,2012 */ +/* COPYRIGHT International Business Machines Corp. 2011,2013 */ /* */ /* p1 */ /* */ @@ -86,7 +86,7 @@ ProcessorCoreType cpu_core_type(); uint8_t cpu_dd_level(); /** @fn cpu_thread_count() - * @brief Get the number of threads per cpu for this proctype + * @brief Get the number of available threads per cpu for this proctype * @return # of threads per cpu */ size_t cpu_thread_count(); @@ -95,6 +95,7 @@ size_t cpu_thread_count(); * @brief Have the kernel start a new core. * * @param[in] pir - PIR value of the first thread on the core. + * @param[in] i_threads - Bitstring of threads to enable (left-justified). * * @note The kernel will start all threads on the requested core even * though the callee only requests with a single PIR value. @@ -104,7 +105,7 @@ size_t cpu_thread_count(); * @retval -ENXIO - The core ID was outside of the range the kernel is * prepared to support. */ -int cpu_start_core(uint64_t pir); +int cpu_start_core(uint64_t pir,uint64_t i_threads); /** * @enum CpuSprNames diff --git a/src/include/sys/mmio.h b/src/include/sys/mmio.h index 610db0124..afdf0d5d1 100644 --- a/src/include/sys/mmio.h +++ b/src/include/sys/mmio.h @@ -97,6 +97,9 @@ enum MMIO_Scratch_Register /** Thread7 Scratch Register - Identifies if Hostboot is active after * host_start_payload. */ MMIO_SCRATCH_HOSTBOOT_ACTIVE = 0x38, + /** Thread7 Scratch Register - Set be SBE for reduced-threads support + * for AVPs. */ + MMIO_SCRATCH_AVP_THREADS = 0x38, }; /** @fn mmio_scratch_read() diff --git a/src/kernel/cpumgr.C b/src/kernel/cpumgr.C index 954232b2d..436930de7 100644 --- a/src/kernel/cpumgr.C +++ b/src/kernel/cpumgr.C @@ -381,7 +381,7 @@ void CpuManager::executePeriodics(cpu_t * i_cpu) } -int CpuManager::startCore(uint64_t pir) +int CpuManager::startCore(uint64_t pir,uint64_t i_threads) { size_t threads = getThreadCount(); pir = pir & ~(threads-1); @@ -394,7 +394,11 @@ int CpuManager::startCore(uint64_t pir) for(size_t i = 0; i < threads; i++) { - Singleton<CpuManager>::instance().startCPU(pir + i); + // Only start the threads we were told to start + if( i_threads & (0x8000000000000000 >> i) ) + { + Singleton<CpuManager>::instance().startCPU(pir + i); + } } __sync_synchronize(); diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C index 9ef1e36b3..615a22e8f 100644 --- a/src/kernel/syscall.C +++ b/src/kernel/syscall.C @@ -5,7 +5,7 @@ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2010,2012 */ +/* COPYRIGHT International Business Machines Corp. 2010,2013 */ /* */ /* p1 */ /* */ @@ -643,7 +643,8 @@ namespace Systemcalls void CpuStartCore(task_t *t) { TASK_SETRTN(t, - CpuManager::startCore(static_cast<uint64_t>(TASK_GETARG0(t)))); + CpuManager::startCore(static_cast<uint64_t>(TASK_GETARG0(t)), + static_cast<uint64_t>(TASK_GETARG1(t)))); }; /** Read SPR values. */ diff --git a/src/lib/syscall_misc.C b/src/lib/syscall_misc.C index b62a10662..7f490e2ac 100644 --- a/src/lib/syscall_misc.C +++ b/src/lib/syscall_misc.C @@ -5,7 +5,7 @@ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2011,2012 */ +/* COPYRIGHT International Business Machines Corp. 2011,2013 */ /* */ /* p1 */ /* */ @@ -66,10 +66,12 @@ size_t cpu_thread_count() return threads; } -int cpu_start_core(uint64_t pir) +int cpu_start_core(uint64_t pir,uint64_t i_threads) { return reinterpret_cast<int64_t>( - _syscall1(MISC_CPUSTARTCORE, reinterpret_cast<void*>(pir))); + _syscall2(MISC_CPUSTARTCORE, + reinterpret_cast<void*>(pir), + reinterpret_cast<void*>(i_threads))); } uint64_t cpu_spr_value(CpuSprNames spr) diff --git a/src/usr/hwpf/hwp/build_winkle_images/build_winkle_images.C b/src/usr/hwpf/hwp/build_winkle_images/build_winkle_images.C index f285bc248..bd63fe764 100644 --- a/src/usr/hwpf/hwp/build_winkle_images/build_winkle_images.C +++ b/src/usr/hwpf/hwp/build_winkle_images/build_winkle_images.C @@ -202,6 +202,11 @@ errlHndl_t applyPoreGenCpuRegs( TARGETING::Target *i_cpuTarget, // and 23.7.3.5 - 6 in Murano Book 4 l_lpcrVal &= ~(0x0000000000002000) ; + TARGETING::Target* sys = NULL; + TARGETING::targetService().getTopLevelTarget(sys); + assert( sys != NULL ); + uint64_t en_threads = sys->getAttr<ATTR_ENABLED_THREADS>(); + uint64_t l_hrmorVal = cpu_spr_value(CPU_SPR_HRMOR); for (TargetHandleList::const_iterator l_coreIds_iter = l_coreIds.begin(); @@ -250,6 +255,12 @@ errlHndl_t applyPoreGenCpuRegs( TARGETING::Target *i_cpuTarget, // fill in lpcr for each thread for ( l_threadId=0; l_threadId < l_cpu_thread_count; l_threadId++ ) { + // Skip threads that we shouldn't be starting + if( !(en_threads & (0x8000000000000000>>l_threadId)) ) + { + continue; + } + TRACDCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "applyPoreGenCpuRegs: core=0x%x,thread=0x%x: ", l_coreId, l_threadId ); diff --git a/src/usr/hwpf/hwp/core_activate/core_activate.C b/src/usr/hwpf/hwp/core_activate/core_activate.C index f8ca1608c..6efce283e 100644 --- a/src/usr/hwpf/hwp/core_activate/core_activate.C +++ b/src/usr/hwpf/hwp/core_activate/core_activate.C @@ -265,9 +265,13 @@ void* call_host_activate_slave_cores( void *io_pArgs ) CHIP_UNIT_ATTR l_coreId = (*l_core)->getAttr<TARGETING::ATTR_CHIP_UNIT>(); FABRIC_NODE_ID_ATTR l_logicalNodeId = - l_processor->getAttr<TARGETING::ATTR_FABRIC_NODE_ID>(); + l_processor->getAttr<TARGETING::ATTR_FABRIC_NODE_ID>(); FABRIC_CHIP_ID_ATTR l_chipId = - l_processor->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>(); + l_processor->getAttr<TARGETING::ATTR_FABRIC_CHIP_ID>(); + TARGETING::Target* sys = NULL; + TARGETING::targetService().getTopLevelTarget(sys); + assert( sys != NULL ); + uint64_t en_threads = sys->getAttr<ATTR_ENABLED_THREADS>(); uint64_t pir = l_coreId << 3; pir |= l_chipId << 7; @@ -278,7 +282,7 @@ void* call_host_activate_slave_cores( void *io_pArgs ) TRACFCOMP( ISTEPS_TRACE::g_trac_isteps_trace, "call_host_activate_slave_cores: Waking %x", pir); - int rc = cpu_start_core(pir); + int rc = cpu_start_core(pir,en_threads); // We purposefully only create one error log here. The only // failure from the kernel is a bad PIR, which means we have diff --git a/src/usr/hwpf/hwp/thread_activate/thread_activate.C b/src/usr/hwpf/hwp/thread_activate/thread_activate.C index 37096abc3..b8b3642e6 100644 --- a/src/usr/hwpf/hwp/thread_activate/thread_activate.C +++ b/src/usr/hwpf/hwp/thread_activate/thread_activate.C @@ -311,8 +311,13 @@ void activate_threads( errlHndl_t& io_rtaskRetErrl ) const fapi::Target l_fapiCore( fapi::TARGET_TYPE_EX_CHIPLET, (const_cast<TARGETING::Target*>(l_masterCore))); - // loop around threads 0-6, SBE starts thread 7 - const uint64_t max_threads = cpu_thread_count(); + // AVPs might enable a subset of the available threads + uint64_t max_threads = cpu_thread_count(); + TARGETING::Target* sys = NULL; + TARGETING::targetService().getTopLevelTarget(sys); + assert( sys != NULL ); + uint64_t en_threads = sys->getAttr<TARGETING::ATTR_ENABLED_THREADS>(); + for( uint64_t thread = 0; thread < max_threads; thread++ ) { // Skip the thread that we're running on @@ -321,6 +326,12 @@ void activate_threads( errlHndl_t& io_rtaskRetErrl ) continue; } + // Skip threads that we shouldn't be starting + if( !(en_threads & (0x8000000000000000>>thread)) ) + { + continue; + } + // send a magic instruction for PHYP Simics to work... MAGIC_INSTRUCTION(MAGIC_SIMICS_CORESTATESAVE); diff --git a/src/usr/intr/intrrp.C b/src/usr/intr/intrrp.C index 775f050f9..96d24a7f5 100644 --- a/src/usr/intr/intrrp.C +++ b/src/usr/intr/intrrp.C @@ -59,6 +59,45 @@ TRAC_INIT(&g_trac_intr, INTR_TRACE_NAME, KILOBYTE, TRACE::BUFFER_SLOW); TASK_ENTRY_MACRO( IntrRp::init ); +/** + * @brief Utility function to get the list of enabled threads + * @return Bitstring of enabled threads + */ +uint64_t get_enabled_threads( void ) +{ + TARGETING::Target* sys = NULL; + TARGETING::targetService().getTopLevelTarget(sys); + assert( sys != NULL ); + uint64_t en_threads = sys->getAttr<TARGETING::ATTR_ENABLED_THREADS>(); + if( en_threads == 0 ) + { + // Read the scratch reg that the SBE setup + // Enabled threads are listed as a bitstring in bits 16:23 + // A value of zero means the SBE hasn't set them up yet + while( en_threads == 0 ) + { + en_threads = mmio_scratch_read(MMIO_SCRATCH_AVP_THREADS); + + //@todo RTC:63991 - Remove this after we get the new SBE image + if( en_threads == 0 ) + { + // Default to all threads enabled + uint64_t max_threads = cpu_thread_count(); + en_threads = + ((1ull << max_threads) - 1ull) << (48ull - max_threads); + } + } + en_threads = en_threads << 16; //left-justify the threads + TRACFCOMP( g_trac_intr, + "Enabled Threads = %.16X", + en_threads ); + + sys->setAttr<TARGETING::ATTR_ENABLED_THREADS>(en_threads); + } + TRACDCOMP( g_trac_intr, "en_threads=%.16X", en_threads ); + return en_threads; +} + void IntrRp::init( errlHndl_t &io_errlHndl_t ) { errlHndl_t err = NULL; @@ -138,11 +177,18 @@ errlHndl_t IntrRp::_init() // Set up link registers to forward all intrpts to master cpu. // // There is one register set per cpu thread. - size_t threads = cpu_thread_count(); + uint64_t max_threads = cpu_thread_count(); + uint64_t en_threads = get_enabled_threads(); PIR_t pir = iv_masterCpu; - for(size_t thread = 0; thread < threads; ++thread) + for(size_t thread = 0; thread < max_threads; ++thread) { + // Skip threads that we shouldn't be starting + if( !(en_threads & (0x8000000000000000>>thread)) ) + { + TRACDCOMP(g_trac_intr,"IntrRp::_init: Skipping thread %d : en_threads=%X",thread,en_threads); + continue; + } pir.threadId = thread; initInterruptPresenter(pir); } @@ -410,10 +456,18 @@ void IntrRp::msgHandler() pir.threadId); size_t threads = cpu_thread_count(); + uint64_t en_threads = get_enabled_threads(); + iv_ipisPending[pir] = IPI_Info_t((1 << threads)-1, msg); for(size_t thread = 0; thread < threads; ++thread) { + // Skip threads that we shouldn't be starting + if( !(en_threads & (0x8000000000000000>>thread)) ) + { + TRACDCOMP(g_trac_intr,"MSG_INTR_ADD_CPU: Skipping thread %d",thread); + continue; + } pir.threadId = thread; initInterruptPresenter(pir); sendIPI(pir); @@ -967,6 +1021,8 @@ void IntrRp::shutDown() iv_cpuList.push_back(iv_masterCpu); size_t threads = cpu_thread_count(); + uint64_t en_threads = get_enabled_threads(); + for(CpuList_t::iterator pir_itr = iv_cpuList.begin(); pir_itr != iv_cpuList.end(); ++pir_itr) @@ -974,6 +1030,12 @@ void IntrRp::shutDown() PIR_t pir = *pir_itr; for(size_t thread = 0; thread < threads; ++thread) { + // Skip threads that were never started + if( !(en_threads & (0x8000000000000000>>thread)) ) + { + TRACDCOMP(g_trac_intr,"IntrRp::shutDown: Skipping thread %d",thread); + continue; + } pir.threadId = thread; deconfigureInterruptPresenter(pir); } diff --git a/src/usr/intr/test/intrtest.H b/src/usr/intr/test/intrtest.H index c12835d77..56670329e 100644 --- a/src/usr/intr/test/intrtest.H +++ b/src/usr/intr/test/intrtest.H @@ -5,7 +5,7 @@ /* */ /* IBM CONFIDENTIAL */ /* */ -/* COPYRIGHT International Business Machines Corp. 2011,2012 */ +/* COPYRIGHT International Business Machines Corp. 2011,2013 */ /* */ /* p1 */ /* */ @@ -59,8 +59,19 @@ class IntrTest: public CxxTest::TestSuite size_t threads = cpu_thread_count(); + //look for an override + TARGETING::Target* sys = NULL; + TARGETING::targetService().getTopLevelTarget(sys); + assert( sys != NULL ); + uint64_t en_threads = sys->getAttr<TARGETING::ATTR_ENABLED_THREADS>(); + for(size_t thread = 0; thread < threads; ++thread) { + if( !(en_threads & (0x8000000000000000>>thread)) ) + { + continue; + } + addr = reinterpret_cast<uint32_t *> (iv_masterAddr + (thread << 12) + 16); // LINK A reg diff --git a/src/usr/targeting/common/xmltohb/attribute_types.xml b/src/usr/targeting/common/xmltohb/attribute_types.xml index 61fa495bc..e9223c7a7 100644 --- a/src/usr/targeting/common/xmltohb/attribute_types.xml +++ b/src/usr/targeting/common/xmltohb/attribute_types.xml @@ -10027,4 +10027,19 @@ Measured in GB</description> </hwpfToHbAttrMap> </attribute> +<attribute> + <id>ENABLED_THREADS</id> + <description> + Bitmask of threads to enable for each processor, + Zero means enable all architected threads + </description> + <simpleType> + <uint64_t> + </uint64_t> + </simpleType> + <persistency>non-volatile</persistency> + <readable/> + <writeable/> +</attribute> + </attributes> diff --git a/src/usr/targeting/common/xmltohb/target_types.xml b/src/usr/targeting/common/xmltohb/target_types.xml index 6b94a88ef..5376ab19c 100644 --- a/src/usr/targeting/common/xmltohb/target_types.xml +++ b/src/usr/targeting/common/xmltohb/target_types.xml @@ -138,9 +138,13 @@ <attribute><id>SBE_IMAGE_OFFSET</id></attribute> <attribute><id>BOOT_VOLTAGE</id></attribute> <attribute><id>SYNC_BETWEEN_STEPS</id></attribute> + <!-- End sbe_config_update attributes --> <!-- proc_select_boot_master attributes --> <attribute><id>PROC_SELECT_BOOT_MASTER</id></attribute> <attribute><id>PROC_SELECT_SEEPROM_IMAGE</id></attribute> + <!-- End proc_select_boot_master attributes --> + + <attribute><id>ENABLED_THREADS</id></attribute> </targetType> <targetType> @@ -364,6 +368,7 @@ <attribute><id>IMT_BASE_ADDR</id></attribute> <attribute><id>IMT_BAR_SIZE</id></attribute> <!-- end Memory Map --> + <!-- PROC_PCIE attributes --> <attribute><id>PROC_PCIE_IOP_CONFIG</id></attribute> <attribute><id>PROC_PCIE_IOP_SWAP</id></attribute> |