diff options
Diffstat (limited to 'pk/ppe42/ppe42_scom.c')
-rw-r--r-- | pk/ppe42/ppe42_scom.c | 232 |
1 files changed, 34 insertions, 198 deletions
diff --git a/pk/ppe42/ppe42_scom.c b/pk/ppe42/ppe42_scom.c index e9fe2e6c..ca0b44c7 100644 --- a/pk/ppe42/ppe42_scom.c +++ b/pk/ppe42/ppe42_scom.c @@ -5,7 +5,7 @@ //----------------------------------------------------------------------------- /// \file ppe42_scom.c -/// \brief Lowest level PK SCOM definitions. +/// \brief Lowest level PK SCOM definitions. /// /// Currently these SCOM functions are only optimized for functionality, not /// speed. Speed optimization will be done when we have full compiler support @@ -21,221 +21,57 @@ #include "pk.h" #include "ppe42_scom.h" +#include "ppe42_msr.h" -uint32_t putscom_abs(uint32_t i_address, uint64_t i_data) +uint32_t putscom_abs(const uint32_t i_address, uint64_t *i_data) { - // CMO-Declaring variables tied to specific registers enables us to protect - // the SCOM data and address variables used in the new stvd and lvd 64-bit - // scom instructions. This protection is needed since the new instructions' - // operands are not yet properly considered by the compiler. - // Note that l_dataH is used to represent the "beginning", i.e. High-order, - // part of the 64-bit data in d8 (i.e., r8+r9). - uint32_t register l_dataH asm("r8")=0; - uint32_t register l_dataL asm("r9")=0; - uint32_t register l_addr_eff asm("r10")=0; - uint32_t register l_scratch asm("r31")=0; + // Perform the Store Virtual Double instruction + PPE_STVD(i_address, &i_data); + + // Get the MSR[SIBRC] as the return code + uint32_t rc = mfmsr(); + rc = ((rc & MSR_SIBRC) >> (32-(MSR_SIBRC_START_BIT + MSR_SIBRC_LEN))); + return (rc); - l_addr_eff = i_address; - l_dataH = (uint32_t)(i_data>>32); - l_dataL = (uint32_t)(i_data); - - // CMO-The following sequence forces usage of l_dataH/L and l_addr_eff - // and thus the population of them as well. - // Further note that unless l_dataH/L are placed right before the following - // sequence, more specifically, if they're placed at the top of putscom(), - // r8, or l_dataH, might be overwritten in the if(chiplet_id) section. - // Secondly, we test l_addr_eff for non-zero through the CR0 register - // (which was populated in the "mr." instruction.) This is to convince the - // compiler that we actually used l_addr_eff for something. - // At present the test result causes no action except to execute the stvd - // instruction in either case. - asm volatile ( \ - "mr. %0, %1 \n" \ - : "=r"(l_scratch) \ - : "r"(l_dataH) ); - asm volatile ( \ - "mr. %0, %1 \n" \ - : "=r"(l_scratch) \ - : "r"(l_dataL) ); - asm volatile ( \ - "mr. %0, %1 \n" \ - : "=r"(l_scratch) \ - : "r"(l_addr_eff) ); - asm volatile ( \ - "beq 0x4 \n" ); - - // CMO-This instruction is not fully supported by the compiler (as of - // 20150108): - // - Works: It is correctly translated into the proper OP code - // format. - // - Works not: The compiler does not seem to recognize the usage - // of the two l_xyz variables in that it doesn't - // know prior to this command that the registers that - // contain the values of l_xyz need to be protected - // up to this point. Thus, we are forced to use those - // two l_xyz variables in some dummy instructions just - // before this point in order to fake protection. - asm volatile ( \ - "stvd %[data], 0(%[effective_address]) \n" \ - : [data]"=r"(l_dataH) \ - : [effective_address]"r"(l_addr_eff) ); - - // CMO-TBD - // Check PIB response code in 0x00001007(17:19) - // Translate PIB rc to PK rc - // Does this rc get reset to zero on success? - // Do we need to check this rc prior to issuing the SCOM? - - return 0; } -uint32_t _putscom( uint32_t i_chiplet_id, uint32_t i_address, uint64_t i_data) +uint32_t _putscom( uint32_t i_chiplet_id, uint32_t i_address, uint64_t *i_data) { - uint32_t l_rc=0; - uint32_t l_cid=0; - uint32_t l_addr_eff=0; - - if (i_chiplet_id) - { - // Accommodate two different ways of supplying the chiplet ID: - // 0xNN000000: Only bits in high-order two nibbles : Valid - // 0x000000NN: Only bits in low-order two nibbles : Valid - // - if ((i_chiplet_id & 0xFF000000) == i_chiplet_id) - { - // Valid: Chiplet ID in high-order two nibbles. - l_cid = i_chiplet_id; - } - else if ((i_chiplet_id & 0x000000FF) == i_chiplet_id) - { - // Valid: Chiplet ID in low-order two nibbles. Convert to high-order. - l_cid = i_chiplet_id << 24; - } - else - { - // Invalid: Invalid type of chiplet ID - PK_TRACE("putscom() : Invalid value of i_chiplet_id (=0x%08X)",i_chiplet_id); - return 1; //CMO-improve Return sensible rc here. - } - - l_addr_eff = (i_address & 0x00FFFFFF) | l_cid; - } - else - { - // Chiplet ID is zero. Accept address as is. - // This is useful for PIB addresses and non-EX chiplets, and even for - // EX chiplets if the fully qualified EX chiplet addr is already known. - l_addr_eff = i_address; - - } - - l_rc = putscom_abs(l_addr_eff, i_data); + // Perform the Store Virtual Double Index instruction + PPE_STVDX(i_chiplet_id, i_address, &i_data); - return l_rc; -} + // Get the MSR[SIBRC] as the return code + uint32_t rc = mfmsr(); + rc = ((rc & MSR_SIBRC) >> (32-(MSR_SIBRC_START_BIT + MSR_SIBRC_LEN))); + return (rc); +} -uint32_t getscom_abs( uint32_t i_address, uint64_t *o_data) +uint32_t getscom_abs( const uint32_t i_address, uint64_t *o_data) { - // CMO-Declaring variables tied to specific registers enables us to protect - // the SCOM data and address variables used in the new stvd and lvd 64-bit - // data instructions. This protection is needed since the new instructions - // are not yet properly considered by the compiler. - // Note that l_dataH is used to represent the "beginning", i.e. High-order, - // part of the 64-bit data in d8 (i.e., r8+r9). - uint32_t register l_dataH asm("r8")=0; - uint32_t register l_dataL asm("r9")=0; - uint32_t register l_addr_eff asm("r10")=0; - uint32_t register l_scratch asm("r31")=0; - - - l_addr_eff = i_address; - - // CMO-The following sequence forces usage of l_addr_eff and thus the - // population of it as well. - // Secondly, we test l_addr_eff for non-zero through the CR0 register - // (which was populated in the "mr." instruction.) This is to convince the - // compiler that we actually used l_addr_eff for something. - // At present the test result causes no action except to execute the lvd - // instruction in either case. - asm volatile ( \ - "mr. %0, %1 \n" \ - : "=r"(l_scratch) \ - : "r"(l_addr_eff) ); - asm volatile ( \ - "beq 0x4 \n" ); - - asm volatile ( \ - "lvd %[data], 0(%[effective_address]) \n" \ - : [data]"=r"(l_dataH) \ - : [effective_address]"r"(l_addr_eff) ); - - // CMO-The following sequence moves the read data, in l_dataH/L, into the - // 64-bit o_data location. - asm volatile ( \ - "stw %0, 0(%1) \n" \ - : "=r"(l_dataH) \ - : "r"(o_data) ); - asm volatile ( \ - "stw %0, 4(%1) \n" \ - : "=r"(l_dataL) \ - : "r"(o_data) ); - - // CMO-TBD - // Check PIB response code in 0x00001007(17:19) - // Translate PIB rc to PK rc + // Perform the Load Virtual Double instruction + PPE_LVD(i_address, &o_data); - return 0; + // Get the MSR[SIBRC] as the return code + uint32_t rc = mfmsr(); + rc = ((rc & MSR_SIBRC) >> (32-(MSR_SIBRC_START_BIT + MSR_SIBRC_LEN))); + return (rc); } -uint32_t _getscom( uint32_t i_chiplet_id, uint32_t i_address, uint64_t *o_data) + +uint32_t _getscom( const uint32_t i_chiplet_id, const uint32_t i_address, uint64_t *o_data) { - uint32_t l_rc=0; - uint32_t l_cid=0; - uint32_t l_addr_eff=0; - - if (i_chiplet_id) - { - // Accommodate two different ways of supplying the chiplet ID: - // 0xNN000000: Only bits in high-order two nibbles : Valid - // 0x000000NN: Only bits in low-order two nibbles : Valid - // - if ((i_chiplet_id & 0xFF000000) == i_chiplet_id) - { - // Valid: Chiplet ID in high-order two nibbles. - l_cid = i_chiplet_id; - } - else if ((i_chiplet_id & 0x000000FF) == i_chiplet_id) - { - // Valid: Chiplet ID in low-order two nibbles. Convert to high-order. - l_cid = i_chiplet_id << 24; - } - else - { - // Invalid: Invalid type of chiplet ID - PK_TRACE("getscom() : Invalid value of i_chiplet_id (=0x%08X)",i_chiplet_id); - return 1; //CMO-improve Return sensible rc here. - } - - l_addr_eff = (i_address & 0x00FFFFFF) | l_cid; - } - else - { - // Chiplet ID is zero. Accept address as is. - // This is useful for PIB addresses and non-EX chiplets, and even for - // EX chiplets if the fully qualified EX chiplet addr is already known. - l_addr_eff = i_address; - } - - l_rc = getscom_abs(l_addr_eff, o_data); - // CMO-TBD - // Check PIB response code in 0x00001007(17:19) - // Translate PIB rc to PK rc + // Perform the Load Virtual Double Index instruction + PPE_LVDX(i_chiplet_id, i_address, &o_data); + + // Get the MSR[SIBRC] as the return code + uint32_t rc = mfmsr(); + rc = ((rc & MSR_SIBRC) >> (32-(MSR_SIBRC_START_BIT + MSR_SIBRC_LEN))); + return (rc); - return l_rc; } |