summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDoug Gilbert <dgilbert@us.ibm.com>2012-04-24 15:19:05 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-05-11 11:58:16 -0500
commit6a973157399568435df01e097e17aabc6be76e65 (patch)
tree30e2b371af39c710ab54fc6368c08a76ccf6842b /src
parentb8ce91454366ae12a4cd510c26f1e87a6629b185 (diff)
downloadtalos-hostboot-6a973157399568435df01e097e17aabc6be76e65.tar.gz
talos-hostboot-6a973157399568435df01e097e17aabc6be76e65.zip
INTR set IPCBAR scom reg on init and add INTR shutdown interface
RTC: 39730 Change-Id: Ib548202f6f935b46cd92e0ddbf48d19b5ff6679a Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/977 Tested-by: Jenkins Server Reviewed-by: Daniel M. Crowell <dcrowell@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src')
-rwxr-xr-xsrc/build/simics/post_model_hook.simics3
-rw-r--r--src/include/kernel/intmsghandler.H46
-rw-r--r--src/include/sys/msg.h1
-rw-r--r--src/kernel/intmsghandler.C15
-rw-r--r--src/usr/intr/intrrp.C206
-rw-r--r--src/usr/intr/intrrp.H36
-rw-r--r--src/usr/intr/test/intrtest.H131
7 files changed, 291 insertions, 147 deletions
diff --git a/src/build/simics/post_model_hook.simics b/src/build/simics/post_model_hook.simics
index 57dc9a117..f2705f615 100755
--- a/src/build/simics/post_model_hook.simics
+++ b/src/build/simics/post_model_hook.simics
@@ -42,7 +42,10 @@ phys-mem.load-file ./sysspd.dat 0x701000
#Setup the mailbox
venice_cec_chip_cmp0.psi_hb->psihb_psihbcr=0x5f00000000000000
+# for mbox on core 0 use:
venice_cec_chip_cmp0.psi_hb->psihb_xivr_fsi=0x0140000000 #02010917
+# for mbox on core 1 use:
+#venice_cec_chip_cmp0.psi_hb->psihb_xivr_fsi=0x0000200140000000
venice_cec_chip_cmp0.psi_hb->psihb_irsn=0x00030000FFFF0000 #0201091b
p8Proc0.proc_fsi2host_mbox->responder_enable=1
diff --git a/src/include/kernel/intmsghandler.H b/src/include/kernel/intmsghandler.H
index 52eadde27..500961668 100644
--- a/src/include/kernel/intmsghandler.H
+++ b/src/include/kernel/intmsghandler.H
@@ -27,6 +27,7 @@
#include <kernel/types.h>
#include <kernel/msghandler.H>
#include <kernel/msg.H>
+#include <builtins.h>
/**
* @class InterruptMsgHdlr
@@ -41,6 +42,31 @@ class InterruptMsgHdlr : public MessageHandler
{
public:
+ /**
+ * Field values for P8
+ * @note This is used to calculate the mmio address offset
+ * from the PIR for the interrupt presenter memory mapped registers.
+ * The masks isolate the node,chip,core, and thread id fields in the
+ * PIR. The LSL values tell how far left a PIR field needs to be
+ * shifted to create a proper mmio offset address.
+ *
+ */
+ enum
+ {
+ P8_PIR_THREADID_MSK = 0x00000007,
+ P8_PIR_COREID_MSK = 0x00000078,
+ P8_PIR_CHIPID_MSK = 0x00000380,
+ P8_PIR_NODEID_MSK = 0x00001C00,
+
+ // Logical Shift Left fields for mmio Base address from PIR.
+ // (IP addr bit pos - PIR bit pos)
+ P8_IP_THREADID_LSL = (12-0),
+ P8_IP_COREID_LSL = (15-3),
+ P8_IP_CHIPID_LSL = (20-7),
+ P8_IP_NODEID_LSL = (23-10),
+ XIRR_ADDR_OFFSET = 4,
+ };
+
// Notes:
// All external interrupts are routed to one cpu core
// External Interrupts are only processed one at a time
@@ -71,6 +97,26 @@ class InterruptMsgHdlr : public MessageHandler
task_t* i_task,int i_rc);
+ ALWAYS_INLINE
+ static uint64_t mmio_offset(uint64_t i_pir)
+ {
+ uint64_t offset = 0;
+
+ // The node and chip id fields are adjacent in both the PIR and
+ // the mmio offset - so they can be done in one shift operation
+ offset |=
+ (i_pir & (P8_PIR_NODEID_MSK | P8_PIR_CHIPID_MSK))
+ << P8_IP_CHIPID_LSL;
+
+ // The core and thread id field are adjacent in both the PIR and
+ // the mmio offset, so they can be done in one shift operation.
+ offset |=
+ (i_pir & (P8_PIR_COREID_MSK | P8_PIR_THREADID_MSK))
+ << P8_IP_THREADID_LSL;
+
+ return offset;
+ }
+
/**
* Create the InterruptMsgHdlr to handle external interrupts
* @param[in] i_msgQ The message queue
diff --git a/src/include/sys/msg.h b/src/include/sys/msg.h
index 4bbf0b265..91dd51ce9 100644
--- a/src/include/sys/msg.h
+++ b/src/include/sys/msg.h
@@ -61,6 +61,7 @@ enum msg_sys_types_t
MSG_INTR_EXTERN, //!< Msg sent from kernel to user space on ext intr
MSG_INTR_ADD_CPU, //!< Add cpu core, data[0] = cpuid (PIR)
+ MSG_INTR_REMOVE_CPU,//!< un-configure intrp on cpu core, data[0] = cpuid
};
// System-defined root queue types
diff --git a/src/kernel/intmsghandler.C b/src/kernel/intmsghandler.C
index e5c86b796..7b994f006 100644
--- a/src/kernel/intmsghandler.C
+++ b/src/kernel/intmsghandler.C
@@ -31,6 +31,7 @@
#include <kernel/taskmgr.H>
#include <kernel/cpu.H>
#include <kernel/scheduler.H>
+#include <arch/ppc.H>
const char* INTR_MSGQ = "/msg/interrupt";
@@ -76,9 +77,12 @@ void InterruptMsgHdlr::handleInterrupt()
// the message.
task_t* t = TaskManager::getCurrentTask();
- // TODO will this always be processor 0 core 0 thread 0?
- // Need a way to pass this addr down from user code?
- uint64_t xirrAddress = (static_cast<uint64_t>(ICPBAR_VAL) << 20) + 4;
+ uint64_t pir = getPIR();
+
+ uint64_t xirrAddress = (static_cast<uint64_t>(ICPBAR_VAL) << 20);
+
+ xirrAddress += mmio_offset(pir); // Add offset for this cpu
+ xirrAddress += XIRR_ADDR_OFFSET; // Add offset for XIRR register
// Ignore HRMOR setting
xirrAddress |= 0x8000000000000000ul;
@@ -100,7 +104,7 @@ void InterruptMsgHdlr::handleInterrupt()
{
cv_instance->sendMessage(MSG_INTR_EXTERN,
(void *)xirr,
- NULL,
+ (void *)pir,
NULL);
}
@@ -109,6 +113,8 @@ void InterruptMsgHdlr::handleInterrupt()
// leave the interrupt presenter locked.
// Does the code that sets up the IP registers need to check to see if
// there is an interrupt sitting there and send an EOI?
+ // Story 41868 - Mask off all interrupts very early - might
+ // resolve this TODO.
// Return the task to the scheduler queue if we did a context-switch.
if (TaskManager::getCurrentTask() != t)
@@ -118,6 +124,7 @@ void InterruptMsgHdlr::handleInterrupt()
}
+// TODO where does this get called from? (story 39878)
void InterruptMsgHdlr::addCpuCore(uint64_t i_pir)
{
// Save the current task in case we context-switch away when sending
diff --git a/src/usr/intr/intrrp.C b/src/usr/intr/intrrp.C
index 5e6771e5b..d05c6c44e 100644
--- a/src/usr/intr/intrrp.C
+++ b/src/usr/intr/intrrp.C
@@ -38,11 +38,14 @@
#include <targeting/common/targetservice.H>
#include <vmmconst.h>
#include <targeting/common/attributes.H>
+#include <devicefw/userif.H>
+
+#define INTR_TRACE_NAME INTR_COMP_NAME
using namespace INTR;
trace_desc_t * g_trac_intr = NULL;
-TRAC_INIT(&g_trac_intr, INTR_COMP_NAME, 2 * 1024);
+TRAC_INIT(&g_trac_intr, INTR_TRACE_NAME, 2 * 1024);
/**
@@ -84,67 +87,30 @@ errlHndl_t IntrRp::_init()
{
errlHndl_t err = NULL;
- // TODO Temporaritly DISABLE in VBU until P8 support is confirmed
- if( TARGETING::is_vpo() )
- {
- iv_isVBU = true;
- }
-
// get the PIR
// Which ever cpu core this is running on is the MASTER cpu
// Make master thread 0
uint32_t cpuid = task_getcpuid();
iv_masterCpu = cpuid;
// If P7 or P7+ core -- need to tweak fields in PIR
- if(cpu_core_type() < CORE_POWER8_MURANO)
+ if(cpu_core_type() == CORE_POWER7 ||
+ cpu_core_type() == CORE_POWER7_PLUS)
{
iv_masterCpu = P7PIR_t(cpuid);
}
iv_masterCpu.threadId = 0;
- TRACFCOMP(g_trac_intr,"node[%d], chip[%d], core[%d], thread[%d]",
+ TRACFCOMP(g_trac_intr,"Master cpu node[%d], chip[%d], core[%d], thread[%d]",
iv_masterCpu.nodeId, iv_masterCpu.chipId, iv_masterCpu.coreId,
iv_masterCpu.threadId);
+ // The base realAddr is the base address for the whole system.
+ // Therefore the realAddr must be based on the processor
+ // that would have the lowest BAR value in the system,
+ // whether it exists or not. In this case n0p0
- uint64_t realAddr = 0;
-
- // TODO Does the BAR scom reg need to be read here or set here??
- // Who sets the BAR?
- //uint64_t size = sizeof(realAddr);
- //TARGETING::TargetService& targetService = TARGETING::targetService();
- //TARGETING::Target* procTarget = NULL;
- //targetService.masterProcChipTargetHandle( procTarget );
- //
- // TODO What if this does not jive with with the PIR?
-
- // TODO Does this need to be read here?
- //err = deviceRead(procTarget,
- // &realAddr,
- // size,
- // DEVICE_SCOM_ADDRESS(ICPBAR_SCOM_ADDR));
- //if(err) return err;
-
- if(realAddr == 0)
- {
- realAddr = (static_cast<uint64_t>(ICPBAR_VAL)) << 34;
- }
-
- // TODO Does this need to be set here?
- // err = deviceWrite(procTarget,
- // &realAddr,
- // size,
- // DEVICE_SCOM_ADDRESS(ICPBAR_SCOM_ADDR));
-
- realAddr &= 0xFFFFFFFC00000000ul; //[0:29] is ICP_BAR
- realAddr >>= 14; //[14:43] is BAR field in real address
-
-
- // The realAddr is the base address for the whole system.
- // Therefore the realAddr must be based on the processor with
- // lowest BAR value in the system. (usually n0p0)
- // TODO Adjust the realAddr if the BAR came from a processor other
- // than cpuid 0
+ // [14:43] is BAR field in address to shift by (34 - 14)
+ uint64_t realAddr = (static_cast<uint64_t>(ICPBAR_VAL)) << 20;
TRACFCOMP(g_trac_intr,"INTR: realAddr = %lx",realAddr);
@@ -154,7 +120,17 @@ errlHndl_t IntrRp::_init()
TRACFCOMP(g_trac_intr,"INTR: vAddr = %lx",iv_baseAddr);
- err = checkAddress(iv_baseAddr);
+ // Set the BAR scom reg
+ TARGETING::Target* procTarget = NULL;
+ TARGETING::targetService().masterProcChipTargetHandle( procTarget );
+
+ err = setBAR(procTarget,iv_masterCpu);
+
+ if(!err)
+ {
+ err = checkAddress(iv_baseAddr);
+ }
+
if(!err)
{
@@ -188,9 +164,6 @@ errlHndl_t IntrRp::enableInterrupts()
{
errlHndl_t err = NULL;
- // TODO Temporarily DISABLE in VBU until P8 support is confirmed
- if(iv_isVBU) return err;
-
// Enable the interrupt on master processor core, thread 0
uint64_t baseAddr = iv_baseAddr + cpuOffsetAddr(iv_masterCpu);
@@ -209,9 +182,6 @@ errlHndl_t IntrRp::disableInterrupts()
errlHndl_t err = NULL;
// Disable the interrupt on master processor core, thread 0
- // TODO Temporarily DISABLE in VBU until P8 support is confirmed
- if(iv_isVBU) return err;
-
uint64_t baseAddr = iv_baseAddr + cpuOffsetAddr(iv_masterCpu);
err = checkAddress(baseAddr);
@@ -245,16 +215,20 @@ void IntrRp::msgHandler()
{
ext_intr_t type = NO_INTERRUPT;
- // type = XISR = XIRR[8:31]
- // priority = XIRR[0:7]
- uint32_t * xirrAddress =
- reinterpret_cast<uint32_t *>(iv_baseAddr+ XIRR_OFFSET+
- cpuOffsetAddr(iv_masterCpu));
-
// xirr was read by interrupt message handler.
// Passed in as data[0]
uint32_t xirr = static_cast<uint32_t>(msg->data[0]);
- type = static_cast<ext_intr_t>(xirr & 0x00FFFFFF);
+ PIR_t pir = static_cast<PIR_t>(msg->data[1]);
+
+ // data[1] has the PIR
+ uint32_t * xirrAddress =
+ reinterpret_cast<uint32_t*>(iv_baseAddr + XIRR_OFFSET +
+ cpuOffsetAddr(pir));
+
+ // type = XISR = XIRR[8:31]
+ // priority = XIRR[0:7]
+ // Use the XISR as the type (for now)
+ type = static_cast<ext_intr_t>(xirr & XISR_MASK);
TRACDCOMP(g_trac_intr,"External Interrupt recieved, Type=%x",type);
@@ -354,8 +328,9 @@ void IntrRp::msgHandler()
{
PIR_t pir = msg->data[0];
// If P7 or P7+ core -- need to tweak fields in PIR
- if(cpu_core_type() < CORE_POWER8_MURANO)
- {
+ if(cpu_core_type() == CORE_POWER7 ||
+ cpu_core_type() == CORE_POWER7_PLUS)
+ {
pir = P7PIR_t(msg->data[0]);
}
@@ -364,6 +339,7 @@ void IntrRp::msgHandler()
pir.nodeId, pir.chipId, pir.coreId,
pir.threadId);
+
size_t threads = cpu_thread_count();
for(size_t thread = 0; thread < threads; ++thread)
@@ -377,6 +353,33 @@ void IntrRp::msgHandler()
}
break;
+ case MSG_INTR_REMOVE_CPU:
+ {
+ PIR_t pir = msg->data[0];
+ if(cpu_core_type() == CORE_POWER7 ||
+ cpu_core_type() == CORE_POWER7_PLUS)
+ {
+ pir = P7PIR_t(msg->data[0]);
+ }
+
+ TRACFCOMP(g_trac_intr,"Remove CPU node[%d], chip[%d],"
+ "core[%d], thread[%d]",
+ pir.nodeId, pir.chipId, pir.coreId,
+ pir.threadId);
+
+ size_t threads = cpu_thread_count();
+
+ for(size_t thread = 0; thread < threads; ++thread)
+ {
+ pir.threadId = thread;
+ deconfigureInterruptPresenter(pir);
+ }
+
+ msg->data[1] = 0;
+ msg_respond(iv_msgQ, msg);
+ }
+ break;
+
default:
msg->data[1] = -EINVAL;
msg_respond(iv_msgQ, msg);
@@ -385,6 +388,36 @@ void IntrRp::msgHandler()
}
+
+errlHndl_t IntrRp::setBAR(TARGETING::Target * i_target,
+ const PIR_t i_pir)
+{
+ errlHndl_t err = NULL;
+
+ uint64_t barValue = static_cast<uint64_t>(ICPBAR_VAL) +
+ (8 * i_pir.nodeId) + i_pir.chipId;
+ barValue <<= 34;
+
+ TRACFCOMP(g_trac_intr,"INTR: Target %p. ICPBAR value: 0x%016lx",
+ i_target,barValue);
+
+ uint64_t size = sizeof(barValue);
+
+ err = deviceWrite(i_target,
+ &barValue,
+ size,
+ DEVICE_SCOM_ADDRESS(ICPBAR_SCOM_ADDR));
+
+ if(err)
+ {
+ TRACFCOMP(g_trac_intr,ERR_MRK"Unable to set IPCBAR");
+ }
+
+ return err;
+}
+
+
+
errlHndl_t IntrRp::registerInterrupt(msg_q_t i_msgQ, ext_intr_t i_type)
{
errlHndl_t err = NULL;
@@ -424,9 +457,6 @@ errlHndl_t IntrRp::registerInterrupt(msg_q_t i_msgQ, ext_intr_t i_type)
void IntrRp::initInterruptPresenter(const PIR_t i_pir) const
{
- // TODO Temporaritly DISABLE in VBU until P8 support is confirmed
- if(iv_isVBU) return;
-
uint64_t baseAddr = iv_baseAddr + cpuOffsetAddr(i_pir);
uint8_t * cppr =
reinterpret_cast<uint8_t*>(baseAddr + CPPR_OFFSET);
@@ -469,6 +499,44 @@ void IntrRp::initInterruptPresenter(const PIR_t i_pir) const
}
+
+void IntrRp::deconfigureInterruptPresenter(const PIR_t i_pir) const
+{
+ uint64_t baseAddr = iv_baseAddr + cpuOffsetAddr(i_pir);
+ uint8_t * cppr =
+ reinterpret_cast<uint8_t*>(baseAddr + CPPR_OFFSET);
+ uint32_t * plinkReg =
+ reinterpret_cast<uint32_t *>(baseAddr + LINKA_OFFSET);
+
+ // non- side effect xirr register
+ uint32_t * xirrAddr =
+ reinterpret_cast<uint32_t *>(baseAddr) + XIRR_RO_OFFSET;
+
+ uint32_t xirr = *xirrAddr & 0x00FFFFFF;
+
+ TRACDCOMP(g_trac_intr,"PIR 0x%x offset: 0x%lx",
+ i_pir.word,
+ cpuOffsetAddr(i_pir));
+
+ // Not sure if this will ever happen, but squawk alittle if it does
+ if(xirr)
+ {
+ TRACFCOMP(g_trac_intr,
+ ERR_MRK
+ "Pending interrupt found on shutdown. CpuId:0x%x XIRR:0x%x",
+ i_pir.word,
+ xirr);
+ }
+
+ *cppr = 0; // Set priority to most favored (off)
+
+ *plinkReg = 0; // Reset link registers - clear all forwarding
+ *(plinkReg + 1) = 0;
+ *(plinkReg + 2) = 0;
+}
+
+
+
errlHndl_t IntrRp::checkAddress(uint64_t i_addr)
{
errlHndl_t err = NULL;
@@ -498,6 +566,12 @@ errlHndl_t IntrRp::checkAddress(uint64_t i_addr)
return err;
}
+// TODO rtc story 39878
+errlHndl_t IntrRp::shutDown()
+{
+ errlHndl_t err = NULL;
+ return err;
+}
// Register a message queue with a particular intr type
errlHndl_t INTR::registerMsgQ(msg_q_t i_msgQ, ext_intr_t i_type)
diff --git a/src/usr/intr/intrrp.H b/src/usr/intr/intrrp.H
index 7078f823f..2900c5276 100644
--- a/src/usr/intr/intrrp.H
+++ b/src/usr/intr/intrrp.H
@@ -34,6 +34,11 @@
struct msg_t;
+namespace TARGETING
+{
+ class Target;
+};
+
namespace INTR
{
class IntrRp
@@ -46,6 +51,13 @@ namespace INTR
*/
static void init( errlHndl_t &io_rtaskRetErrl );
+ /**
+ * This function is registered with init for shutdown
+ * processing of the interrupt presenter.
+ * TODO Story 39878
+ */
+ static errlHndl_t shutDown();
+
protected:
/**
@@ -54,8 +66,7 @@ namespace INTR
IntrRp() :
iv_msgQ(NULL),
iv_baseAddr(0),
- iv_masterCpu(0),
- iv_isVBU(false) {}
+ iv_masterCpu(0) {}
/**
* Destructor
@@ -71,11 +82,13 @@ namespace INTR
enum
{
+ XIRR_RO_OFFSET = 0, //!< offset to XIRR (poll)
CPPR_OFFSET = 4, //!< offset to CPPR (1 byte)
XIRR_OFFSET = 4, //!< offset to XIRR (4 bytes)
LINKA_OFFSET = 16, //!< offset to LINKA register
LINKB_OFFSET = 20, //!< offset to LINKB register
LINKC_OFFSET = 24, //!< offset to LINKC register
+ XISR_MASK = 0x00FFFFFF, //!< XISR MASK in XIRR register
};
// If the interrupt can't be handled by the current chip there are
@@ -184,7 +197,6 @@ namespace INTR
Registry_t iv_registry; //!< registered interrupt type
uint64_t iv_baseAddr; //!< Base address of hw INTR regs
PIR_t iv_masterCpu; //!< Master cpu PIR
- bool iv_isVBU; //!< TODO Don't run on VBU for now
private: //functions
@@ -220,13 +232,29 @@ namespace INTR
void initInterruptPresenter(const PIR_t i_pir) const;
/**
+ * Deconfigure the interrupt presenter registers
+ * @param[in] i_pir, the PIR value for the presenter
+ */
+ void deconfigureInterruptPresenter(const PIR_t i_pir) const;
+
+ /**
+ * Set the IPCBAR scom register
+ * @param[in] i_target, the Target.
+ * @param[in] i_pir, The pir for this processor
+ */
+ errlHndl_t setBAR(TARGETING::Target * i_target,
+ const PIR_t i_pir);
+
+ /**
* Calculate the adress offset for the given cpu
* @param[in] i_pir PIR value for the presenter
* @return the offset
*/
- ALWAYS_INLINE
+ ALWAYS_INLINE
uint64_t cpuOffsetAddr(const PIR_t i_pir) const
{
+ // TODO when P7 support is removed then change this
+ // to use InterruptMsgHdlr::mmio_offset()
uint64_t offset = (i_pir.nodeId * 8) + i_pir.chipId;
offset <<= 20;
switch (cpu_core_type())
diff --git a/src/usr/intr/test/intrtest.H b/src/usr/intr/test/intrtest.H
index ae9ce135f..f7c6b37f4 100644
--- a/src/usr/intr/test/intrtest.H
+++ b/src/usr/intr/test/intrtest.H
@@ -32,6 +32,9 @@
#include <targeting/common/attributes.H>
#include <sys/time.h>
#include <sys/mmio.h>
+#include <sys/task.h>
+#include <sys/misc.h>
+#include <kernel/intmsghandler.H>
extern trace_desc_t * g_trac_intr;
@@ -44,73 +47,41 @@ class IntrTest: public CxxTest::TestSuite
*/
void test_verifyState( void )
{
- // TODO Temporaritly DISABLE in VBU until P8 support is verfied
- if( TARGETING::is_vpo() )
+
+ uint32_t * addr = reinterpret_cast<uint32_t *>(iv_masterAddr);
+
+ if(*addr != 0xFF000000) // XIRR ro reg
{
- return;
+ TS_FAIL
+ ("INTR:Master cpu not initialized-XIRR @ %p = 0x%08x",
+ addr,*addr);
}
- //// Add support for second chip (dummy)
- ////uint32_t fake_pir = 0x00000001 << 5; // P7
- //uint32_t fake_pir = 0x00000001 << 7; // P8
- //msg_q_t intr_msgQ = msg_q_resolve(INTR_MSGQ);
- //msg_t * msg = msg_allocate();
- //msg->type = INTR::MSG_INTR_ADD_CPU_USR;
- //msg->data[0] = fake_pir;
-
- //msg_sendrecv(intr_msgQ, msg);
- //msg_free(msg);
+ size_t threads = cpu_thread_count();
- // all the simics registers
- for(uint64_t chip = 0; chip < 1; ++chip)
+ for(size_t thread = 0; thread < threads; ++thread)
{
- // simics P8 appears to support 8 threads on 1 core.
- // simics P7 appears to support 4 threads on 2 cores.
- // for P7, pretending to have 8 threads works because the
- // bit fields for cores and threads are contiguous so we can
- // let the thread count overflow into the core field. so this
- // works for p7 as well.
- for(uint64_t thread = 0; thread < 8; ++thread)
+ addr = reinterpret_cast<uint32_t *>
+ (iv_masterAddr + (thread << 12) + 16); // LINK A reg
+
+ uint32_t linkVal = iv_masterPIR | 0x40000000;
+
+ if((*addr != linkVal) ||
+ (*(addr+1) != linkVal) ||
+ (*(addr+2) != (linkVal | 0x80000000)))
{
- uint64_t offset = (chip << 20) | (thread << 12);
-
- uint32_t * addr =
- reinterpret_cast<uint32_t *>(iv_baseAddr + offset);
-
- if(offset == 0) // Master cpu
- {
- if(*addr != 0xFF000000)
- {
- TS_FAIL
- ("INTR:Master cpu not initialized-XIRR@%p=0x%08x",
- addr,*addr);
- }
- }
-
- // TODO remove restriction when/if simics supports
- // more than 2 chips and 4 threads each
- if (chip < 2 && thread < 4)
- {
- if(offset != 0 && *addr != 0)
- {
- TS_FAIL("INTR:Chip %ld Thread %ld bad XIRR@%p=0x%08x",
- chip,thread,addr,*addr);
- }
-
-
-
- if(*(addr+4) != 0x40000000 ||
- *(addr+5) != 0x40000000 ||
- *(addr+6) != 0xC0000000)
- {
- TS_FAIL("INTR:Chip %ld Thread %ld bad LINKS"
- " 0x%08x 0x%08x 0x%08x",
- chip,thread,
- *(addr+4),*(addr+5),*(addr+6));
- }
- }
+ TS_FAIL("INTR:Bad LINKS on chipid 0x%08x "
+ "Links: 0x%08x 0x%08x 0x%08x",
+ ((uint32_t)iv_masterPIR + thread),
+ *addr,
+ *(addr + 1),
+ *(addr + 2)
+ );
}
+
}
+
+ // Potentially could check all link registers on other chips
}
/**
@@ -118,13 +89,8 @@ class IntrTest: public CxxTest::TestSuite
*/
void test_enableDisable( void )
{
- // TODO Temporaritly DISABLE in VBU until P8 support is confirmed
- if( TARGETING::is_vpo() )
- {
- return;
- }
- uint32_t * addr = reinterpret_cast<uint32_t *>(iv_baseAddr);
+ uint32_t * addr = reinterpret_cast<uint32_t *>(iv_masterAddr);
errlHndl_t err = INTR::disableExternalInterrupts();
@@ -162,7 +128,8 @@ class IntrTest: public CxxTest::TestSuite
*/
void test_intr( void )
{
- // TODO Temporaritly DISABLE in VBU until P8 support is confirmed
+
+ // DISABLE in VBU
if( TARGETING::is_vpo() )
{
return;
@@ -182,7 +149,7 @@ class IntrTest: public CxxTest::TestSuite
// Force an interrupt by writing to the MFFR on master
volatile uint8_t * mfrr =
- reinterpret_cast<uint8_t *>(iv_baseAddr+12);
+ reinterpret_cast<uint8_t *>(iv_masterAddr+12);
*(mfrr) = 0x55;
*(mfrr) = 0xff;
@@ -206,12 +173,28 @@ class IntrTest: public CxxTest::TestSuite
}
- IntrTest() : CxxTest::TestSuite()
- {
- iv_baseAddr = reinterpret_cast<uint64_t>
- (mmio_dev_map(reinterpret_cast<void*>(cv_realAddr),THIRTYTWO_MB));
- TRACDCOMP(g_trac_intr,"IntrTest()> iv_baseAddr=0x%.X",iv_baseAddr);
- };
+ IntrTest() : CxxTest::TestSuite()
+ {
+ iv_baseAddr = reinterpret_cast<uint64_t>
+ (mmio_dev_map(reinterpret_cast<void*>(cv_realAddr),THIRTYTWO_MB));
+
+ TRACDCOMP(g_trac_intr,"IntrTest()> iv_baseAddr=0x%.X",iv_baseAddr);
+
+ task_affinity_pin(); // pin this task to current cpu
+ task_affinity_migrate_to_master(); // Move to the master cpu
+
+ // Get the master cpu id, thread 0
+ iv_masterPIR = task_getcpuid();
+
+ TRACDCOMP(g_trac_intr,"IntrTest()> iv_masterPIR=0x%.X",iv_masterPIR);
+
+ iv_masterPIR &= 0xFFFFFFF8;
+
+ task_affinity_unpin(); // unpin this task
+
+ iv_masterAddr = InterruptMsgHdlr::mmio_offset(iv_masterPIR) + iv_baseAddr;
+
+ };
~IntrTest()
@@ -222,6 +205,8 @@ class IntrTest: public CxxTest::TestSuite
private:
uint64_t iv_baseAddr;
+ uint64_t iv_masterAddr;
+ cpuid_t iv_masterPIR;
static const uint64_t cv_realAddr;
};
OpenPOWER on IntegriCloud