summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xinclude/ppe_compiler.mk59
-rw-r--r--include/proc_hcd_common.H20
-rw-r--r--pk/ppe42/ppe42_scom.c232
-rw-r--r--pk/ppe42/ppe42_scom.h101
4 files changed, 188 insertions, 224 deletions
diff --git a/include/ppe_compiler.mk b/include/ppe_compiler.mk
new file mode 100755
index 00000000..7db9a4ca
--- /dev/null
+++ b/include/ppe_compiler.mk
@@ -0,0 +1,59 @@
+# Make header to set up PPE Compiler
+#
+ifndef CC_VERSION
+export CC_VERSION = 4.8.3
+endif
+
+ifndef CC_TARGET
+export CC_TARGET = powerpc-buildroot-linux-gnu
+endif
+
+# GCC libraries
+ifndef LIB_GCC_DIR
+export LIB_GCC_DIR = $(CC_ROOT)/usr/lib/gcc/$(CC_TARGET)/$(CC_VERSION)
+endif
+LIB_DIRS += -L$(LIB_GCC_DIR)
+
+# GCC libraries
+ifndef LIB_GCC_BASE
+export LIB_GCC_BASE = $(CC_ROOT)/usr/lib/gcc/$(CC_TARGET)
+endif
+LIB_DIRS += -L$(LIB_GCC_BASE)
+
+# GCC libraries
+ifndef LIB_BASE
+export LIB_BASE = $(CC_ROOT)/usr/lib
+endif
+LIB_DIRS += -L$(LIB_BASE)
+
+# Shared Object C and C++ libraries
+ifndef LIB_TARGET
+export LIB_TARGET = $(CC_ROOT)/usr/$(CC_TARGET)/lib
+endif
+#CLIBS += $(LIB_TARGET)/libstdc++.a
+#LIB_DIRS += -L$(LIB_TARGET)
+
+# Static C and C++ libraries
+ifndef LIB_CLIB_DIR
+export LIB_CLIB_DIR = $(CC_ROOT)/usr/$(CC_TARGET)/sysroot/lib
+endif
+LIB_DIRS += -L$(LIB_CLIB_DIR)
+
+# Runtime Static C and C++ libraries
+ifndef LIB_CULIB_DIR
+export LIB_CULIB_DIR = $(CC_ROOT)/usr/$(CC_TARGET)/sysroot/usr/lib
+endif
+LIB_DIRS += -L$(LIB_CULIB_DIR)
+
+GCCLIBS += $(LIB_CULIB_DIR)/libstdc++.a
+GCCLIBS += $(LIB_CULIB_DIR)/libm.a
+GCCLIBS += $(LIB_CULIB_DIR)/libc.a
+
+ifdef ENABLE_UCLIB
+GCCLIBS += $(LIB_CULIB_DIR)/uclibc_nonshared.a
+GCCLIBS += $(LIB_CULIB_DIR)/crt1.o
+GCCLIBS += $(LIB_CULIB_DIR)/crti.o
+endif
+
+GCCLIBS += $(LIB_GCC_DIR)/libgcc.a
+GCCLIBS += $(LIB_GCC_DIR)/libgcc_eh.a
diff --git a/include/proc_hcd_common.H b/include/proc_hcd_common.H
new file mode 100644
index 00000000..51cc1285
--- /dev/null
+++ b/include/proc_hcd_common.H
@@ -0,0 +1,20 @@
+#ifndef __PROC_HCD_COMMON_H
+#define __PROC_HCD_COMMON_H
+
+/// \file proc_hcd_common.H
+/// \brief Standard bit-manipulation macros (C and Assembler) for PORE code
+
+/// \defgroup be64_bits Bit manipulation for 64-bit Big-Endian values
+///
+/// \note These macros only work in the assembler context because we build our
+/// assemblers to do 64-bit arithmetic, which is required for PORE assembly.
+///
+/// @{
+
+/// Create a multi-bit mask of \a n bits starting at bit \a b
+#define BITS(b, n) ((ULL(0xffffffffffffffff) << (64 - (n))) >> (b))
+
+/// Create a single bit mask at bit \a b
+#define BIT(b) BITS((b), 1)
+
+#endif // __PROC_HCD_COMMON_H
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;
}
diff --git a/pk/ppe42/ppe42_scom.h b/pk/ppe42/ppe42_scom.h
index 0d57e5d4..886a44b8 100644
--- a/pk/ppe42/ppe42_scom.h
+++ b/pk/ppe42/ppe42_scom.h
@@ -25,28 +25,89 @@
#define PCB_ERROR_PACKET_ERROR 6
#define PCB_ERROR_TIMEOUT 7
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/// PPE Load Virtual Double operation
+#define PPE_LVD(_m_address, _m_data) \
+asm volatile \
+ ( \
+ "lvd %[data], 0(%[address]) \n" \
+ : [data]"=&r"(*_m_data) \
+ : "[data]"(*_m_data), \
+ [address]"r"(_m_address) \
+ );
+
+
+// PPE Store Virtual Double operation
+#define PPE_STVD(_m_address, _m_data) \
+asm volatile \
+ ( \
+ "stvd %[data], 0(%[address]) \n" \
+ : [data]"=&r"(*_m_data) \
+ : "[data]"(*_m_data), \
+ [address]"r"(_m_address) \
+ : "memory" \
+ );
+
+/// PPE Load Virtual Double Indexed operation
+#define PPE_LVDX(_m_base, _m_offset, _m_data) \
+asm volatile \
+ ( \
+ "lvdx %[data], %[base], %[offset] \n" \
+ : [data]"=&r"(*_m_data) \
+ : "[data]"(*_m_data), \
+ [base]"r"(_m_base), \
+ [offset]"r"(_m_offset) \
+ );
+
+
+// PPE Store Virtual Double Indexed operation
+#define PPE_STVDX(_m_base, _m_offset, _m_data) \
+asm volatile \
+ ( \
+ "stvdx %[data], %[base], %[offset] \n" \
+ : [data]"=&r"(*_m_data) \
+ : "[data]"(*_m_data), \
+ [base]"r"(_m_base), \
+ [offset]"r"(_m_offset) \
+ : "memory" \
+ );
+
+#define PPE_MFMSR(_m_data) \
+asm volatile \
+ ( \
+ "mfmsr %[data] \n" \
+ : [data]"=&r"(*_m_data) \
+ : "[data]"(*_m_data) \
+ );
+
/// @brief putscom with absolute address
-/// @param [in] i_address Fully formed SCOM address
-/// @param [in] i_data uint64_t data to be written
+/// @param [in] i_address Fully formed SCOM address
+/// @param [in] i_data Pointer to uint64_t data to be written. A pointer is used
+/// to optimize the underlying hardware execution
///
/// @retval On PPE42 platform, unmasked errors will take machine check interrupts
-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);
/// @brief getscom with absolute address
/// @param [in] i_address Fully formed SCOM address
/// @param [in] *o_data Pointer to uint64_t data read
///
/// @retval On PPE42 platform, unmasked errors will take machine check interrupts
-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);
/// @brief Implementation of PPE putscom functionality
/// @param [in] i_chiplet Chiplet ID (@todo Should only be right justified)
/// @param [in] i_address Base SCOM address
-/// @param [in] i_data uint64_t data to be written
+/// @param [in] i_data Pointer to uint64_t data to be written. A pointer is used
+/// to optimize the underlying hardware execution
///
/// @retval On PPE42 platform, unmasked errors will take machine check interrupts
-uint32_t _putscom( uint32_t i_chiplet, uint32_t i_address, uint64_t i_data);
+uint32_t _putscom( const uint32_t i_chiplet, const uint32_t i_address, uint64_t *i_data);
/// @brief Implementation of PPE getscom functionality
@@ -57,31 +118,19 @@ uint32_t _putscom( uint32_t i_chiplet, uint32_t i_address, uint64_t i_data);
/// @retval On PPE42 platform, unmasked errors will take machine check interrupts
uint32_t _getscom( uint32_t i_chiplet, uint32_t i_address, uint64_t *o_data);
-
-/// Macro to abstract the underlying putscom function so that it might be replaced
-/// later with different implementations. Used directly by low level PPE calls
-/// but also used by the FAPI2 API implementation
-/*
-#define putscom (_m_chiplet, _m_address, _m_data) { \
- _putscom( _m_chiplet, _m_address, _m_data); \
-};
-*/
-extern inline uint32_t putscom(uint32_t i_chiplet, uint32_t i_address, uint64_t i_data)
+extern inline uint32_t putscom(const uint32_t i_chiplet, const uint32_t i_address, uint64_t *i_data)
{
return _putscom(i_chiplet, i_address, i_data);
}
-/// Macro to abstract the underlying getscom function so that it might be replaced
-/// later with different implementations. Used directly by low level PPE calls
-/// but also used by the FAPI2 API implementation
-/*
-#define getscom (i_chiplet, i_address, o_data) { \
- _getscom( i_chiplet, i_address, o_data); \
-};
-*/
-extern inline uint32_t getscom(uint32_t i_chiplet, uint32_t i_address, uint64_t *o_data)
-{
+
+extern inline uint32_t getscom(const uint32_t i_chiplet, const uint32_t i_address, uint64_t *o_data)
+{
return _getscom(i_chiplet, i_address, o_data);
}
+#ifdef __cplusplus
+} // extern C
+#endif
+
#endif // __PK_SCOM_H__
OpenPOWER on IntegriCloud