More OpenPower Firmware code released: OCC

Inside the IBM POWER8 chip there’s another processor! That’s right folks, you get another CPU for no extra cost (It’s a lot funnier if you say these previous two sentences as if you were presenting an informercial for a special TV offer).

It is, however, not what you’d consider a general purpose processor. It is, in fact, a PowerPC 405 – so your POWER8 processor also has another PowerPC chip in it. What’s the purpose of this chip? It’s named the On Chip Controller and it has the job of helping make the main processor (the POWER8) work.

It has two jobs:

  • Monitor temperature and keep the system thermally safe
  • Monitor power usage and keep the system power safe

It runs a hard Real Time OS which has just been released up on github.com/open-power/occ

There’s more complete documentation on OCC here.

It’s fairly exciting to see more of the software that runs on every POWER8 system make it out into the world.

5 thoughts on “More OpenPower Firmware code released: OCC

  1. Intetersing! I’ve not heard about that.

    The documentation says “There is one OCC per POWER processor chip.” Does that mean that for scale-out systems we have two OCCs per DCM?

  2. Hi Alexander and Stewart,

    AFAICT from the OCC init/reset functions in Hostboot, and following the functions to write to the SCOM registers (per Chip), there’s one OCC per chip.

    This is contrary to this video, which shows one OCC per ‘P8 Module’ (which, as in DCM – dual chip module – has 2 chips), but this is not a very tech-details video.
    http://youtu.be/Z-4Q0_l9nt8?t=13s

    The spec (open-power/docs) doesn’t mention per-core/per-chip.. so I think the best official answer would be from its author, Martha Broyles. Or someone who is more familiar w/ the Hostboot source code and can be certain of my hyphotesis above.

    In summary:

    both
    //Start the OCC on primary chip of DCM
    and
    // Start the OCC on slave chip of DCM
    call
    p8_occ_control() for a specific chip target
    which calls
    putScom -> fapiPutScom
    which
    * @brief Writes a SCOM register on a Chip

    Trace/details:

    open-power/hostboot/src/usr/hwpf/hwp/occ/occ_common.C

    * @brief Start OCC for specified DCM pair of processors.
    * If 2nd input is NULL, OCC will be setup on just
    * one target.
    *
    * @param[in] i_target0: target of first processor in DCM pair
    * @param[in] i_target1: target of second processor in DCM pair
    * @param[out] o_failedTarget failed target in case of an error
    *
    * @return errlHndl_t Error log of startOCC failed
    */
    errlHndl_t startOCC (Target* i_target0,
    Target* i_target1,
    Target *& o_failedTarget)
    {

    //==============================
    //Start the OCC on primary chip of DCM
    //==============================
    FAPI_INVOKE_HWP( l_errl,
    p8_occ_control,
    l_fapiTarg0,
    PPC405_RESET_OFF,
    PPC405_BOOT_MEM );

    //==============================
    // Start the OCC on slave chip of DCM
    //==============================
    if ( l_fapiTarg1.getType() != fapi::TARGET_TYPE_NONE )
    {
    FAPI_INVOKE_HWP( l_errl,
    p8_occ_control,
    l_fapiTarg1,
    PPC405_RESET_OFF,
    PPC405_BOOT_MEM );

    open-power/hostboot/src/usr/hwpf/hwp/occ/occ_procedures/p8_pm_prep_for_reset.C

    // ******************************************************************
    // Put OCC PPC405 into reset safely
    // ******************************************************************
    FAPI_INF(“Put OCC PPC405 into reset safely”);
    FAPI_DBG(“Executing: p8_occ_control.C”);

    FAPI_EXEC_HWP(rc, p8_occ_control, i_primary_chip_target, PPC405_RESET_SEQUENCE, 0);

    if ( i_secondary_chip_target.getType() != TARGET_TYPE_NONE )
    {
    FAPI_EXEC_HWP(rc, p8_occ_control, i_secondary_chip_target, PPC405_RESET_SEQUENCE, 0);

    }

    open-power/hostboot/src/usr/hwpf/hwp/occ/occ_procedures/p8_occ_control.C

    /// \param[in] i_target => Chip Target
    /// \param[in] i_ppc405_reset_ctrl => PPC405_RESET_NULL : do nothing PPC405_RESET_OFF : set ppc405 reset=0 PPC405_RESET_ON : set ppc405 reset=1
    /// \param[in] i_ppc405_boot_ctrl => PPC405_BOOT_NULL : do nothing PPC405_BOOT_SRAM : boot from sram PPC405_BOOT_MEM : boot from memory PPC405_BOOT_OLD : boot from sram (OLD tests)

    /// \retval FAPI_RC_SUCCESS
    /// \retval ERROR defined in xml

    fapi::ReturnCode
    p8_occ_control(const Target& i_target, const uint8_t i_ppc405_reset_ctrl, const uint8_t i_ppc405_boot_ctrl)
    {

    case PPC405_RESET_OFF:

    rc = putScom(i_target, OCC_CONTROL_AND_0x0006B001, ~BIT(0));

    case PPC405_RESET_SEQUENCE:

    rc = putScom(i_target, OCC_CONTROL_OR_0x0006B002, BIT(0));

    open-power/hostboot/src/include/usr/hwpf/fapi/fapiHwAccess.H

    /**
    * @brief Writes a SCOM register on a Chip
    * @param[in] i_target Target to operate on
    * @param[in] i_address Scom address to write to
    * @param[in] i_data ecmdDataBufferBase object that holds data to write into
    * address
    * @return ReturnCode. Zero on success, else platform specified error
    */
    fapi::ReturnCode fapiPutScom(const fapi::Target& i_target,
    const uint64_t i_address,
    ecmdDataBufferBase & i_data);

    open-power/hostboot/src/usr/hwpf/plat/fapiPlatHwAccess.C

    fapi::ReturnCode platPutScom(const fapi::Target& i_target,
    const uint64_t i_address,
    ecmdDataBufferBase & i_data)
    {

    // Extract the component pointer
    TARGETING::Target* l_target =
    reinterpret_cast(i_target.get());

    open-power/hostboot/src/include/usr/targeting/common/target.H

    typedef Target* TargetHandle_t;

    open-power/hostboot/src/usr/diag/prdf/test/prdfsimScrDataSet.H

    typedef TARGETING::TargetHandle_t ChipId

  3. Oops, typo:

    Here: the spec (open-power/docs) doesn’t mention per-core/per-chip …
    Read: per-*module*/per-chip.

    And all the indentation is gone in previous comment. :/ But you can get the idea.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.