summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThi Tran <thi@us.ibm.com>2012-01-13 10:29:25 -0600
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-02-07 13:49:45 -0600
commit859335d953a59c25de64a414c344d0a22d0911cb (patch)
treec606dbbbe0cbbfa3275ca0d644ac417e258b84b9
parent0f454c096f27c06cb93ad442c0e14fc734464867 (diff)
downloadtalos-hostboot-859335d953a59c25de64a414c344d0a22d0911cb.tar.gz
talos-hostboot-859335d953a59c25de64a414c344d0a22d0911cb.zip
Initial VSBE Supports
Fixed test case failure Change-Id: Ie388aebddacba99dfc6cc04e5fe98f0e8ca8b4bd Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/520 Tested-by: Jenkins Server Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
-rw-r--r--config.mk33
-rwxr-xr-ximg/sbe_pnor.binbin0 -> 31360 bytes
-rwxr-xr-xsrc/build/trace/tracepp2
-rw-r--r--src/include/usr/initservice/initsvcreasoncodes.H3
-rw-r--r--src/makefile12
-rw-r--r--src/usr/initservice/extinitsvc/extinitsvctasks.H35
-rw-r--r--src/usr/makefile2
-rw-r--r--src/usr/pore/fapiporeve/fapiPoreVe.C749
-rw-r--r--src/usr/pore/fapiporeve/fapiPoreVeArg.C265
-rw-r--r--src/usr/pore/fapiporeve/fapiPoreVeArg.H197
-rw-r--r--src/usr/pore/fapiporeve/makefile39
-rw-r--r--src/usr/pore/makefile27
-rwxr-xr-xsrc/usr/pore/poreve/hook/sbe_pnor.hooks.cc798
-rw-r--r--src/usr/pore/poreve/makefile67
-rw-r--r--src/usr/pore/poreve/model/bebits.H48
-rw-r--r--src/usr/pore/poreve/model/modelerror.H149
-rw-r--r--src/usr/pore/poreve/model/poreaddress.C78
-rw-r--r--src/usr/pore/poreve/model/poreaddress.H117
-rw-r--r--src/usr/pore/poreve/model/poreconstants.H275
-rw-r--r--src/usr/pore/poreve/model/poreinterface.C242
-rw-r--r--src/usr/pore/poreve/model/poreinterface.H346
-rw-r--r--src/usr/pore/poreve/model/poremodel.C439
-rw-r--r--src/usr/pore/poreve/model/poremodel.H733
-rw-r--r--src/usr/pore/poreve/model/poreregister.C295
-rw-r--r--src/usr/pore/poreve/model/poreregister.H275
-rw-r--r--src/usr/pore/poreve/model/porestate.C93
-rw-r--r--src/usr/pore/poreve/model/porestate.H108
-rw-r--r--src/usr/pore/poreve/model/transaction.C90
-rw-r--r--src/usr/pore/poreve/model/transaction.H251
-rw-r--r--src/usr/pore/poreve/pore_model/ibuf/pore_bus.c934
-rw-r--r--src/usr/pore/poreve/pore_model/ibuf/pore_fi2c.c550
-rw-r--r--src/usr/pore/poreve/pore_model/ibuf/pore_fi2c.h47
-rw-r--r--src/usr/pore/poreve/pore_model/ibuf/pore_ibuf.h222
-rw-r--r--src/usr/pore/poreve/pore_model/ibuf/pore_inline_decode.c129
-rw-r--r--src/usr/pore/poreve/pore_model/ibuf/pore_inline_decode.h207
-rw-r--r--src/usr/pore/poreve/pore_model/ibuf/pore_model.c3130
-rw-r--r--src/usr/pore/poreve/pore_model/ibuf/pore_regs.h671
-rw-r--r--src/usr/pore/poreve/pore_model/include/pore_model.h741
-rw-r--r--src/usr/pore/poreve/pore_model/include/pore_wrap.h102
-rw-r--r--src/usr/pore/poreve/pore_model/include/vsbe.H193
-rw-r--r--src/usr/pore/poreve/pore_model/wrapper/vsbe.C692
-rw-r--r--src/usr/pore/poreve/porevesrc/bus.C900
-rw-r--r--src/usr/pore/poreve/porevesrc/bus.H661
-rw-r--r--src/usr/pore/poreve/porevesrc/create.C46
-rw-r--r--src/usr/pore/poreve/porevesrc/fasti2c.C604
-rw-r--r--src/usr/pore/poreve/porevesrc/fasti2c.H564
-rw-r--r--src/usr/pore/poreve/porevesrc/hookmanager.C575
-rw-r--r--src/usr/pore/poreve/porevesrc/hookmanager.H859
-rw-r--r--src/usr/pore/poreve/porevesrc/pib2cfam.C167
-rw-r--r--src/usr/pore/poreve/porevesrc/pib2cfam.H94
-rw-r--r--src/usr/pore/poreve/porevesrc/pore.C269
-rw-r--r--src/usr/pore/poreve/porevesrc/pore.H259
-rw-r--r--src/usr/pore/poreve/porevesrc/poreve.C480
-rw-r--r--src/usr/pore/poreve/porevesrc/poreve.H535
-rw-r--r--src/usr/pore/poreve/porevesrc/sbevital.C82
-rw-r--r--src/usr/pore/poreve/porevesrc/sbevital.H85
-rw-r--r--src/usr/pore/poreve/poreveutil.C35
-rw-r--r--src/usr/pore/test/makefile37
-rw-r--r--src/usr/pore/test/poretest.H181
59 files changed, 19804 insertions, 15 deletions
diff --git a/config.mk b/config.mk
index 7436bab41..7f1a5fb47 100644
--- a/config.mk
+++ b/config.mk
@@ -76,10 +76,11 @@ TRACEPP = ${ROOTPATH}/src/build/trace/tracepp
CUSTOM_LINKER_EXE = ${ROOTPATH}/src/build/linker/linker
CUSTOM_LINKER = i686-mcp6-jail ${CUSTOM_LINKER_EXE}
-CC_RAW = ppc64-mcp6-gcc
+CC_RAW = ppc64-mcp6-gcc -std=c99
CXX_RAW = ppc64-mcp6-g++
CC = ${TRACEPP} ${CC_RAW}
CXX = ${TRACEPP} ${CXX_RAW}
+
LD = ppc64-mcp6-ld
OBJDUMP = ppc64-mcp6-objdump
APYFIPSHDR = apyfipshdr
@@ -144,9 +145,21 @@ ${OBJDIR}/%.o ${OBJDIR}/%.list : %.C
${CXX} -c ${CXXFLAGS} $< -o $@ ${INCFLAGS} -iquote .
${OBJDUMP} -dCS $@ > $(basename $@).list
+# Compiling *.cc files
+${OBJDIR}/%.o ${OBJDIR}/%.list : %.cc
+ mkdir -p ${OBJDIR}
+ ${CXX} -c ${CXXFLAGS} $< -o $@ ${INCFLAGS} -iquote .
+ ${OBJDUMP} -dCS $@ > $(basename $@).list
+
${OBJDIR}/%.o ${OBJDIR}/%.list : %.c
mkdir -p ${OBJDIR}
- ${CC} -c ${CFLAGS} -std=c99 $< -o $@ ${INCFLAGS} -iquote .
+ # Override to use C++ compiler in place of C compiler
+ # CC_OVERRIDE is set in the makefile of the component
+ifndef CC_OVERRIDE
+ ${CC} -c ${CFLAGS} $< -o $@ ${INCFLAGS} -iquote .
+else
+ ${CXX} -c ${CXXFLAGS} $< -o $@ ${INCFLAGS} -iquote .
+endif
${OBJDUMP} -dCS $@ > $(basename $@).list
${OBJDIR}/%.o : %.S
@@ -160,10 +173,17 @@ ${OBJDIR}/%.dep : %.C
sed 's,\($*\)\.o[ :]*,${OBJDIR}/\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
+${OBJDIR}/%.dep : %.cc
+ mkdir -p ${OBJDIR}; \
+ rm -f $@; \
+ ${CXX_RAW} -M ${CXXFLAGS} $< -o $@.$$$$ ${INCFLAGS} -iquote .; \
+ sed 's,\($*\)\.o[ :]*,${OBJDIR}/\1.o $@ : ,g' < $@.$$$$ > $@; \
+ rm -f $@.$$$$
+
${OBJDIR}/%.dep : %.c
mkdir -p ${OBJDIR}; \
rm -f $@; \
- ${CC_RAW} -M ${CFLAGS} -std=c99 $< -o $@.$$$$ ${INCFLAGS} -iquote .; \
+ ${CC_RAW} -M ${CFLAGS} $< -o $@.$$$$ ${INCFLAGS} -iquote .; \
sed 's,\($*\)\.o[ :]*,${OBJDIR}/\1.o $@ : ,g' < $@.$$$$ > $@; \
rm -f $@.$$$$
@@ -262,11 +282,16 @@ ${BEAMDIR}/%.beam : %.C
${BEAMCMD} -I ${INCDIR} ${CXXFLAGS} ${BEAMFLAGS} $< \
--beam::complaint_file=$@ --beam::parser_file=/dev/null
-${BEAMDIR}/%.beam : %.c
+${BEAMDIR}/%.beam : %.cc
mkdir -p ${BEAMDIR}
${BEAMCMD} -I ${INCDIR} ${CXXFLAGS} ${BEAMFLAGS} $< \
--beam::complaint_file=$@ --beam::parser_file=/dev/null
+${BEAMDIR}/%.beam : %.c
+ mkdir -p ${BEAMDIR}
+ ${BEAMCMD} -I ${INCDIR} ${CFLAGS} ${BEAMFLAGS} $< \
+ --beam::complaint_file=$@ --beam::parser_file=/dev/null
+
${BEAMDIR}/%.beam : %.S
echo Skipping ASM file.
diff --git a/img/sbe_pnor.bin b/img/sbe_pnor.bin
new file mode 100755
index 000000000..1671aa81e
--- /dev/null
+++ b/img/sbe_pnor.bin
Binary files differ
diff --git a/src/build/trace/tracepp b/src/build/trace/tracepp
index dfeda9d55..bc570aeb8 100755
--- a/src/build/trace/tracepp
+++ b/src/build/trace/tracepp
@@ -163,7 +163,7 @@ while(defined($opt = shift @ARGV)) {
# an object or archive, ignore this but give it to cc
push @ccopts, $opt;
print "found object/archive '$opt'\n" if $debug;
- } elsif ($opt =~ m/\.c[xp]*$/i) {
+ } elsif ($opt =~ m/\.c[cxp]*$/i) {
# the source file(s). we should only get one
if (defined $source) {
print STDERR "don't know to handle two source files, aborting\n";
diff --git a/src/include/usr/initservice/initsvcreasoncodes.H b/src/include/usr/initservice/initsvcreasoncodes.H
index 77428c770..077aedabf 100644
--- a/src/include/usr/initservice/initsvcreasoncodes.H
+++ b/src/include/usr/initservice/initsvcreasoncodes.H
@@ -65,7 +65,8 @@ enum InitServiceModuleID
START_I2C_ERRL_ID = 0x19,
START_INTR_ERRL_ID = 0x1A,
START_SPD_ERRL_ID = 0x1B,
-
+ START_FAPIPOREVE_ERRL_ID = 0x1C,
+ START_POREVE_ERRL_ID = 0x1D,
// Internal InitService codes
INITSVC_START_TASK_MOD_ID = 0x20,
diff --git a/src/makefile b/src/makefile
index 517fcb9b3..ddd9dc6ca 100644
--- a/src/makefile
+++ b/src/makefile
@@ -49,21 +49,27 @@ BASE_MODULES = trace errl devicefw scom xscom initservice taskargs \
EXTENDED_MODULES = targeting ecmddatabuffer fapi hwp plat \
extinitsvc istepdisp hwas fsi fsiscom i2c intr \
- spd dmi_training
+ spd dmi_training fapiporeve poreve
DIRECT_BOOT_MODULES = example
RUNTIME_MODULES =
+
TESTCASE_MODULES = cxxtest testerrl testdevicefw testsyslib \
testscom testxscom testtargeting testinitservice testkernel \
testhwpf testecmddatabuffer initsvctasktest2 testcxxtest \
- testpnor testi2c testfsi testvfs testhwas testintr testspd
+ testpnor testi2c testfsi testvfs testhwas testintr testspd \
+ testpore
RELOCATABLE_IMAGE_LDFLAGS = -pie --export-dynamic
hbicore_OBJECTS = ${BASE_OBJECTS} ${DIRECT_BOOT_OBJECTS} ${STUB_TESTCASE_OBJECT}
hbicore_MODULES = ${BASE_MODULES} ${DIRECT_BOOT_MODULES}
hbicore_EXTENDED_MODULES = ${EXTENDED_MODULES}
-hbicore_DATA_MODULES = sample.if dimmspd.dat
+#@todo - Temporary workaround
+# The sbe_pnor.bin is manually built from CVS SBE procedure files in CVS then copy
+# into HostBoot for now. HostBoot build team will have a process of building sbe_pnor
+# image later.
+hbicore_DATA_MODULES = sample.if dimmspd.dat sbe_pnor.bin
hbicore_LIDNUMBER = 80f00100
diff --git a/src/usr/initservice/extinitsvc/extinitsvctasks.H b/src/usr/initservice/extinitsvc/extinitsvctasks.H
index c21f218ef..ca783b488 100644
--- a/src/usr/initservice/extinitsvc/extinitsvctasks.H
+++ b/src/usr/initservice/extinitsvc/extinitsvctasks.H
@@ -178,15 +178,11 @@ const TaskInfo g_exttaskinfolist[] = {
}
},
-
- // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- // NOTE: libistepdisp.so needs to always be last in this list!!
- // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
/**
* @brief External interrupt resource provider
*/
{
- "libintr.so", // tasknmae
+ "libintr.so", // taskname
NULL, // no ptr to fnct
{
START_TASK, // task type
@@ -196,6 +192,35 @@ const TaskInfo g_exttaskinfolist[] = {
},
/**
+ * @brief VSBE FAPI interface code library.
+ */
+ {
+ "libfapiporeve.so" , // taskname
+ NULL, // no pointer to fn
+ {
+ INIT_TASK, // task type
+ EXT_IMAGE, // Extended Module
+ START_FAPIPOREVE_ERRL_ID // module id
+ }
+ },
+
+ /**
+ * @brief VSBE code library
+ */
+ {
+ "libporeve.so" , // taskname
+ NULL, // no pointer to fn
+ {
+ INIT_TASK, // task type
+ EXT_IMAGE, // Extended Module
+ START_POREVE_ERRL_ID // module id
+ }
+ },
+
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ // NOTE: libistepdisp.so needs to always be last in this list!!
+ // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+ /**
* @brief IStep Dispatcher task, runs ISteps
*
*
diff --git a/src/usr/makefile b/src/usr/makefile
index 71365d0c1..60a40d488 100644
--- a/src/usr/makefile
+++ b/src/usr/makefile
@@ -27,6 +27,6 @@ OBJS = module_init.o
SUBDIRS = example.d trace.d cxxtest.d testcore.d errl.d devicefw.d \
scom.d xscom.d targeting.d initservice.d hwpf.d \
ecmddatabuffer.d pnor.d i2c.d vfs.d fsi.d hwas.d fsiscom.d \
- intr.d spd.d
+ intr.d spd.d pore.d
include ${ROOTPATH}/config.mk
diff --git a/src/usr/pore/fapiporeve/fapiPoreVe.C b/src/usr/pore/fapiporeve/fapiPoreVe.C
new file mode 100644
index 000000000..bf44a6102
--- /dev/null
+++ b/src/usr/pore/fapiporeve/fapiPoreVe.C
@@ -0,0 +1,749 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/fapiporeve/fapiPoreVe.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// -*- mode: C++; c-file-style: "linux"; -*-
+// $Id: fapiPoreVe.C,v 1.22 2012/01/09 20:55:27 jeshua Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/fapiPoreVe.C,v $
+//------------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2011
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//------------------------------------------------------------------------------
+// *! TITLE : fapiPoreVe.C
+// *! DESCRIPTION : Creates and runs a PoreVe
+// *! OWNER NAME : Jeshua Smith Email: jeshua@us.ibm.com
+// *! BACKUP NAME : John Bordovsky Email: johnb@us.ibm.com
+// #! ADDITIONAL COMMENTS :
+//
+// The purpose of this procedure is to initialize and run a PoreVe
+//
+// Assume: Any memory images and start state desired are passed in
+//
+// Procedure Summary:
+// Create new PoreVe (pass in master target)
+// Reset the PoreVe (pass in slave target)
+// Install start state, if passed in
+// Install hooks
+// Install each memory image passed in
+// Set entry point
+// Set break point
+// Run the requested number of instructions
+// Extract end state
+// Destroy PoreVe
+//
+
+
+
+//----------------------------------------------------------------------
+// Includes
+//----------------------------------------------------------------------
+#include "poreve.H"
+#include <fapi.H>
+#include "fapiPoreVeArg.H"
+
+//For hooks
+#ifndef __HOSTBOOT_MODULE
+#include <dlfcn.h>
+#endif
+#include "hookmanager.H"
+
+#ifdef FAPIECMD
+extern "C" {
+#endif
+
+using namespace vsbe;
+
+const uint32_t MBOX_SBEVITAL_0x0005001C = 0x0005001C;
+
+
+//******************************************************************************
+// fapiPoreVe function
+//******************************************************************************
+fapi::ReturnCode fapiPoreVe(
+ const fapi::Target i_target,
+ std::list<uint64_t> & io_sharedObjectArgs)
+
+{
+ fapi::ReturnCode rc; //JDS TODO - set initial values
+ PoreVe *poreve = NULL;
+ FapiPoreVeOtherArg *pOtherArg = NULL;
+
+ //----------------------------------------------------------------------
+ // Find the PORE type
+ //----------------------------------------------------------------------
+ std::list<uint64_t>::iterator itr;
+ for( itr = io_sharedObjectArgs.begin();
+ (itr != io_sharedObjectArgs.end()) && (poreve == NULL);
+ itr++ )
+ {
+ FapiPoreVeArg *arg = reinterpret_cast<FapiPoreVeArg *>(*itr);
+
+ //----------------------------------------------------------------------
+ // Use PORE type and pdbgArg to create poreve
+ //----------------------------------------------------------------------
+ if( arg->iv_type == ARG_OTHER )
+ {
+ FapiPoreVeOtherArg *thisArg = (FapiPoreVeOtherArg *)arg;
+ pOtherArg = thisArg;
+ fapi::Target masterTarget = i_target; //JDS TODO - get this from an attribute
+ poreve = PoreVe::create( thisArg->iv_poreType,
+ masterTarget,
+ thisArg->iv_pdbgArgs );
+ }
+ }
+ if( poreve == NULL )
+ {
+ FAPI_ERR( "Failed to create poreve\n" );
+ rc = 0xDEAD0000;
+ }
+
+
+ //----------------------------------------------------------------------
+ // Reset the PoreVe and set slave target
+ //----------------------------------------------------------------------
+ if( rc.ok() ) {
+ poreve->reset( i_target );
+ }
+
+ //----------------------------------------------------------------------
+ // Parse the arguments
+ //----------------------------------------------------------------------
+ FapiPoreVeStateArg *stateArg = NULL;
+ for( itr = io_sharedObjectArgs.begin();
+ (itr != io_sharedObjectArgs.end()) && rc.ok(); itr++ )
+ {
+ FapiPoreVeArg *arg = reinterpret_cast<FapiPoreVeArg *>(*itr);
+
+ //----------------------------------------------------------------------
+ // Install the start state (if passed in)
+ //----------------------------------------------------------------------
+ if( arg->iv_type == ARG_STATE )
+ {
+ stateArg = (FapiPoreVeStateArg *)arg;
+ if( stateArg->iv_installState )
+ {
+ PoreState * p_state = (PoreState *)stateArg->iv_data;
+
+#ifndef __HOSTBOOT_MODULE
+ if( p_state == NULL )
+ {
+ p_state = new PoreState();
+ stateArg->iv_data=p_state;
+ char* state_rc;
+ int linenum = 0;
+
+ stateArg->iv_fd = fopen( stateArg->iv_filename, "r" );
+ if( stateArg->iv_fd == NULL )
+ {
+ FAPI_ERR( "Failed to open state file %s\n", stateArg->iv_filename );
+ rc = 0xDEAD4321;
+ }
+ else
+ {
+ do
+ {
+ char line[200];
+ state_rc = fgets( line, sizeof(line), stateArg->iv_fd );
+ linenum++;
+ if( state_rc != NULL )
+ {
+ //Get register name
+ char* reg = strtok( line, " =" );
+
+ PoreRegisterOffset reg_offset;
+ if( strcmp( reg, "PORE_STATUS" ) == 0 ) {
+ reg_offset = PORE_STATUS;
+ } else if( strcmp( reg, "PORE_CONTROL" ) == 0 ) {
+ reg_offset = PORE_CONTROL;
+ } else if( strcmp( reg, "PORE_RESET" ) == 0 ) {
+ reg_offset = PORE_RESET;
+ } else if( strcmp( reg, "PORE_ERROR_MASK" ) == 0 ) {
+ reg_offset = PORE_ERROR_MASK;
+ } else if( strcmp( reg, "PORE_PRV_BASE_ADDR0" ) == 0 ) {
+ reg_offset = PORE_PRV_BASE_ADDR0;
+ } else if( strcmp( reg, "PORE_PRV_BASE_ADDR1" ) == 0 ) {
+ reg_offset = PORE_PRV_BASE_ADDR1;
+ } else if( strcmp( reg, "PORE_OCI_MEMORY_BASE_ADDR0" ) == 0 ) {
+ reg_offset = PORE_OCI_MEMORY_BASE_ADDR0;
+ } else if( strcmp( reg, "PORE_OCI_MEMORY_BASE_ADDR1" ) == 0 ) {
+ reg_offset = PORE_OCI_MEMORY_BASE_ADDR1;
+ } else if( strcmp( reg, "PORE_TABLE_BASE_ADDR" ) == 0 ) {
+ reg_offset = PORE_TABLE_BASE_ADDR;
+ } else if( strcmp( reg, "PORE_EXE_TRIGGER" ) == 0 ) {
+ reg_offset = PORE_EXE_TRIGGER;
+ } else if( strcmp( reg, "PORE_SCRATCH0" ) == 0 ) {
+ reg_offset = PORE_SCRATCH0;
+ } else if( strcmp( reg, "PORE_SCRATCH1" ) == 0 ) {
+ reg_offset = PORE_SCRATCH1;
+ } else if( strcmp( reg, "PORE_SCRATCH2" ) == 0 ) {
+ reg_offset = PORE_SCRATCH2;
+ } else if( strcmp( reg, "PORE_IBUF_01" ) == 0 ) {
+ reg_offset = PORE_IBUF_01;
+ } else if( strcmp( reg, "PORE_IBUF_2" ) == 0 ) {
+ reg_offset = PORE_IBUF_2;
+ } else if( strcmp( reg, "PORE_DBG0" ) == 0 ) {
+ reg_offset = PORE_DBG0;
+ } else if( strcmp( reg, "PORE_DBG1" ) == 0 ) {
+ reg_offset = PORE_DBG1;
+ } else if( strcmp( reg, "PORE_PC_STACK0" ) == 0 ) {
+ reg_offset = PORE_PC_STACK0;
+ } else if( strcmp( reg, "PORE_PC_STACK1" ) == 0 ) {
+ reg_offset = PORE_PC_STACK1;
+ } else if( strcmp( reg, "PORE_PC_STACK2" ) == 0 ) {
+ reg_offset = PORE_PC_STACK2;
+ } else if( strcmp( reg, "PORE_ID_FLAGS" ) == 0 ) {
+ reg_offset = PORE_ID_FLAGS;
+ } else if( strcmp( reg, "PORE_DATA0" ) == 0 ) {
+ reg_offset = PORE_DATA0;
+ } else if( strcmp( reg, "PORE_MEM_RELOC" ) == 0 ) {
+ reg_offset = PORE_MEM_RELOC;
+ } else if( strcmp( reg, "PORE_I2C_E0_PARAM" ) == 0 ) {
+ reg_offset = PORE_I2C_E0_PARAM;
+ } else if( strcmp( reg, "PORE_I2C_E1_PARAM" ) == 0 ) {
+ reg_offset = PORE_I2C_E1_PARAM;
+ } else if( strcmp( reg, "PORE_I2C_E2_PARAM" ) == 0 ) {
+ reg_offset = PORE_I2C_E2_PARAM;
+ } else if( strcmp( reg, "PORE_HIDDEN_STATE_0" ) == 0) {
+ reg_offset = PORE_HIDDEN_STATE_0;
+ } else if( strcmp( reg, "PORE_HIDDEN_STATE_1" ) == 0) {
+ reg_offset = PORE_HIDDEN_STATE_1;
+ } else if( strcmp( reg, "PORE_HIDDEN_STATE_2" ) == 0) {
+ reg_offset = PORE_HIDDEN_STATE_2;
+ } else if( strcmp( reg, "PORE_HIDDEN_STATE_3" ) == 0) {
+ reg_offset = PORE_HIDDEN_STATE_3;
+ } else if( strcmp( reg, "PORE_HIDDEN_STATE_4" ) == 0) {
+ reg_offset = PORE_HIDDEN_STATE_4;
+ } else {
+ FAPI_ERR("Unknown reg name %s on line %i\n",
+ reg, linenum );
+ reg = NULL;
+ } //strcmp reg vs regname
+
+ if( reg != NULL )
+ {
+ //get the register value
+ char* value = strtok( NULL, " =" );
+ if( value != NULL )
+ {
+ uint64_t value_64 = strtoull( value, NULL, 16 );
+ ModelError me = p_state->put( reg_offset, value_64 );
+ FAPI_INF( "Set %s(0x%X) to 0x%llX\n", reg, reg_offset, value_64 );
+ if( me != ME_SUCCESS )
+ {
+ FAPI_ERR( "Model error parsing state. Errno(%i)\n",
+ (int)me);
+ }
+ }
+ else
+ {
+ FAPI_ERR( "Error parsing value of %s on line %i\n",
+ reg, linenum );
+ }
+ } //if reg != NULL
+ } //if state_rc != NULL
+ } while ( state_rc != NULL ); //able to read a line
+ fclose( stateArg->iv_fd );
+ } //able to open statefile
+ }
+ else
+ {
+ FAPI_INF( "State pointer was passed in, so not reading state from file\n" );
+ }
+#endif
+
+ ModelError me = poreve->iv_pore.installState( *p_state );
+ if( me != ME_SUCCESS )
+ {
+ FAPI_ERR( "Model error installing state. Errno(%i)\n", (int)me);
+ rc = 0xDEAD1400 | me;
+ }
+ } //if install state
+ } //end state arg processing
+
+ //----------------------------------------------------------------------
+ // Install hooks
+ //----------------------------------------------------------------------
+ else if( arg->iv_type == ARG_HOOKS )
+ {
+#ifndef __HOSTBOOT_MODULE
+ FapiPoreVeHooksArg *thisArg = (FapiPoreVeHooksArg *)arg;
+
+ //Load hooks (note: this must be done after poreve is created)
+ void *handle = dlopen( thisArg->iv_filename, RTLD_NOW);
+ if (handle == 0)
+ {
+ FAPI_ERR( "dlopen() failed; See dlerror() string below\n%s\n",
+ dlerror());
+ FAPI_ERR( "Failed to load hooks file\n" );
+ rc = 0xDEAD0002;
+ }
+ else
+ {
+ FAPI_INF( "Loaded hooks file %s\n", thisArg->iv_filename );
+ poreve->iv_pore.enableAddressHooks(true);
+ }
+#endif
+ }
+
+ //----------------------------------------------------------------------
+ // Install each memory image passed in
+ // (OTPROM, PNOR, SEEPROM, MAINMEM, SRAM)
+ //----------------------------------------------------------------------
+ else
+ {
+ FapiPoreVeMemArg *thisArg = (FapiPoreVeMemArg *)arg;
+
+ //OTPROM
+ if( thisArg->iv_type == ARG_OTPROM )
+ {
+ poreve->iv_otpromMemory.map( thisArg->iv_base,
+ thisArg->iv_size,
+ (ACCESS_MODE_READ),
+ thisArg->iv_data,
+ thisArg->iv_crcEnable );
+ }
+
+ //PNOR
+ else if( thisArg->iv_type == ARG_PNOR )
+ {
+ poreve->iv_pnorMemory.map( thisArg->iv_base,
+ thisArg->iv_size,
+ (ACCESS_MODE_READ|ACCESS_MODE_WRITE),
+ thisArg->iv_data,
+ thisArg->iv_crcEnable );
+ }
+
+ //SEEPROM
+ else if( thisArg->iv_type == ARG_SEEPROM )
+ {
+ poreve->iv_seepromMemory.map( thisArg->iv_base,
+ thisArg->iv_size,
+ (ACCESS_MODE_READ),
+ thisArg->iv_data,
+ thisArg->iv_crcEnable );
+ }
+
+ //MAINMEM
+ else if( thisArg->iv_type == ARG_MAINMEM )
+ {
+ poreve->iv_mainMemory.map( thisArg->iv_base,
+ thisArg->iv_size,
+ (ACCESS_MODE_READ|ACCESS_MODE_WRITE),
+ thisArg->iv_data,
+ thisArg->iv_crcEnable );
+ }
+
+ //SRAM
+ else if( thisArg->iv_type == ARG_SRAM )
+ {
+ poreve->iv_sramMemory.map( thisArg->iv_base,
+ thisArg->iv_size,
+ (ACCESS_MODE_READ|ACCESS_MODE_WRITE),
+ thisArg->iv_data,
+ thisArg->iv_crcEnable );
+ }
+
+ //Unknown type
+ else if( thisArg->iv_type != ARG_OTHER )
+ {
+ FAPI_ERR( "Got an arg of an unknown type\n");
+ rc = 0xDEAD0005;
+ }
+ } //end memory args
+ } //end parse options
+
+ //----------------------------------------------------------------------
+ // Set entry point
+ //----------------------------------------------------------------------
+ if( pOtherArg->iv_entryPoint != NULL )
+ {
+ FAPI_INF( "Looking up entry point %s\n", pOtherArg->iv_entryPoint );
+
+ GlobalSymbolInfo epInfo;
+ bool symbolFound = false;
+ HookError he = HookManager::findGlobalSymbol(
+ pOtherArg->iv_entryPoint,
+ symbolFound,
+ epInfo);
+ if( !symbolFound || (he != HOOK_OK) )
+ {
+ FAPI_ERR( "Failed to find entry point \"%s\" in hooks file\n",
+ pOtherArg->iv_entryPoint);
+ rc = 0xDEAD2000 | he;
+ HookManager::report();
+ }
+ else
+ {
+ //Make sure entry point is a valid type
+ if( epInfo.iv_type != 'T' )
+ {
+ FAPI_ERR( "Entry point is of ivalid type %c\n", epInfo.iv_type );
+ rc = 0xDEAD0007;
+ }
+ else
+ {
+ //Set PC to the entry point
+ ModelError me =
+ poreve->iv_pore.setPc( epInfo.iv_address );
+ if( me != ME_SUCCESS )
+ {
+ FAPI_ERR( "Model error setting PC. Errno(%i)\n", (int)me);
+ rc = 0xDEAD1000 | me;
+ }
+ }
+ }
+ }
+
+ //----------------------------------------------------------------------
+ // Set breakpoint
+ //----------------------------------------------------------------------
+ if( pOtherArg->iv_breakpoint != NULL )
+ {
+ FAPI_INF( "Looking up breakpoint %s\n", pOtherArg->iv_breakpoint );
+
+ GlobalSymbolInfo bpInfo;
+ bool symbolFound = false;
+ HookError he = HookManager::findGlobalSymbol(
+ pOtherArg->iv_breakpoint,
+ symbolFound,
+ bpInfo);
+ if( !symbolFound || (he != HOOK_OK) )
+ {
+ FAPI_ERR( "Failed to find breakpoint \"%s\" in hooks file\n",
+ pOtherArg->iv_breakpoint);
+ rc = 0xDEAD2000 | he;
+ HookManager::report();
+ }
+ else
+ {
+ //Make sure break point is a valid type
+ if( bpInfo.iv_type != 'T' )
+ {
+ FAPI_ERR( "Break point is of ivalid type %c\n", bpInfo.iv_type );
+ rc = 0xDEAD0007;
+ }
+ else
+ {
+ //Set the break point
+ ModelError me =
+ poreve->iv_pore.setBreakpoint( bpInfo.iv_address );
+ if( me != ME_SUCCESS )
+ {
+ FAPI_ERR( "Model error setting breakpoint. Errno(%i)\n",
+ (int)me);
+ rc = 0xDEAD1000 | me;
+ }
+ }
+ }
+ }
+
+ //----------------------------------------------------------------------
+ // Set MRR
+ //----------------------------------------------------------------------
+ if( pOtherArg->iv_mrr != 0 )
+ {
+ FAPI_INF( "Setting MRR to 0x%llX\n", pOtherArg->iv_mrr );
+
+ ModelError me = poreve->iv_pore.registerWrite( vsbe::PORE_MEM_RELOC,
+ pOtherArg->iv_mrr & 0x00000003fffffc00ull, sizeof(uint64_t) );
+ if( me != ME_SUCCESS )
+ {
+ FAPI_ERR( "Model error setting MRR. Errno(%i)\n", (int)me);
+ rc = 0xDEAD3000 | me;
+ }
+ }
+
+ //----------------------------------------------------------------------
+ // Run the requested number of instructions
+ //----------------------------------------------------------------------
+ if( rc.ok() ) {
+ uint64_t o_actualNumInstructionsRun = 0;
+ int runStatus = poreve->run( pOtherArg->iv_instructionCount,
+ o_actualNumInstructionsRun );
+ FAPI_INF( "PORE ran %llu instructions, and returned status 0x%X\n",
+ o_actualNumInstructionsRun, runStatus);
+
+ if( runStatus != 0 )
+ {
+ //Parse out each status bit
+ if( runStatus & PORE_STATUS_HALTED )
+ {
+ FAPI_INF( "PORE is stopped at a HALT instruction\n");
+ runStatus &= ~PORE_STATUS_HALTED;
+
+ //Check the SBE VITAL reg halt code for success
+ uint64_t data_64;
+ int pib_rc;
+ ModelError me;
+ me = poreve->getscom(MBOX_SBEVITAL_0x0005001C, data_64, pib_rc);
+
+ if( me == ME_SUCCESS )
+ {
+ if( pib_rc == 0 )
+ {
+ //Bits 12:15 are halt code; code 0xF = success
+ uint32_t haltcode = (data_64 >> 48) & 0x0000000F;
+ if( haltcode != 0xF )
+ {
+ FAPI_ERR( "Halt code is 0x%x (ERROR)\n", haltcode );
+ rc = 0xDEAD6660 | haltcode;
+ }
+ else
+ {
+ FAPI_INF( "Halt code is 0x%x (SUCCESS)\n",haltcode);
+ rc = 0;
+ }
+ }
+ else
+ {
+ FAPI_ERR("PIB error getting halt code (error code %i)\n",
+ pib_rc );
+ rc = 0xDEAD6650 | pib_rc;
+ }
+ }
+ else
+ {
+ FAPI_ERR( "Model error getting halt code (me=0x%x)\n", me );
+ rc = 0xDEAD6500 | me;
+ }
+ }
+ if( runStatus & PORE_STATUS_ERROR_HALT )
+ {
+ FAPI_ERR( "PORE is stopped due to an architected error\n");
+ runStatus &= ~PORE_STATUS_ERROR_HALT;
+ rc = 0xDEAD7777;
+ }
+ if( runStatus & PORE_STATUS_HARDWARE_STOP )
+ {
+ FAPI_INF( "PORE is stopped\n");
+ runStatus &= ~PORE_STATUS_HARDWARE_STOP;
+ }
+ if( runStatus & PORE_STATUS_BREAKPOINT )
+ {
+ FAPI_INF( "PORE is stopped at a breakpoint\n");
+ runStatus &= ~PORE_STATUS_BREAKPOINT;
+ }
+ if( runStatus & PORE_STATUS_TRAP )
+ {
+ FAPI_INF( "PORE is stopped at a TRAP instruction\n");
+ runStatus &= ~PORE_STATUS_TRAP;
+ }
+ if( runStatus & PORE_STATUS_MODEL_ERROR )
+ {
+ FAPI_ERR( "PORE is stopped due to a modeling error\n");
+ runStatus &= ~PORE_STATUS_MODEL_ERROR;
+ rc = 0xDEAD0003; //JDS TODO - create a real return code
+ }
+ if( runStatus & PORE_STATUS_DEBUG_STOP )
+ {
+ FAPI_INF( "PORE is stopped due to a user request (probably a hook)\n");
+ runStatus &= ~PORE_STATUS_DEBUG_STOP;
+ }
+ //If we still have bits set, we missed something
+ if( runStatus )
+ {
+ FAPI_ERR( "PORE is stopped with an unknown status code:0x%X\n",
+ runStatus);
+ rc = 0xDEAD0004; //JDS TODO - create a real return code
+ }
+ } else { //runStatus == 0
+ FAPI_IMP( "PORE ran the requested number of instructions without hitting any stop conditions\n");
+ }
+
+ if( (pOtherArg->iv_instructionCount != RUN_UNLIMITED) &&
+ (pOtherArg->iv_instructionCount != o_actualNumInstructionsRun) )
+ {
+ FAPI_IMP( "PORE only ran %llu of the %llu instructions you requested\n",
+ o_actualNumInstructionsRun,
+ pOtherArg->iv_instructionCount );
+ }
+ } //if( rc.ok() )
+
+ //----------------------------------------------------------------------
+ // Extract end state
+ //----------------------------------------------------------------------
+ if( stateArg != NULL && stateArg->iv_extractState )
+ {
+ ModelError me;
+ PoreState * p_state = (PoreState *)stateArg->iv_data;
+
+ if( p_state == NULL )
+ {
+ p_state = new PoreState();
+ }
+ me = poreve->iv_pore.extractState( *p_state );
+
+#ifndef __HOSTBOOT_MODULE
+ stateArg->iv_fd = fopen( stateArg->iv_filename, "w" );
+ if( stateArg->iv_fd == NULL ) {
+ FAPI_ERR( "Unable to write state to \"%s\"\n",
+ stateArg->iv_filename );
+ rc = 0xDEAD1550;
+ } else {
+ uint64_t data_64;
+
+#define printreg(offset, reg) \
+ me = p_state->get(offset, data_64); if (me != 0) break; \
+ fprintf( stateArg->iv_fd, reg, data_64 );
+
+ do
+ {
+ printreg(vsbe::PORE_STATUS, "PORE_STATUS = 0x%llX\n" );
+ printreg(vsbe::PORE_CONTROL, "PORE_CONTROL = 0x%llX\n" );
+ printreg(vsbe::PORE_RESET, "PORE_RESET = 0x%llX\n" );
+ printreg(vsbe::PORE_ERROR_MASK, "PORE_ERROR_MASK = 0x%llX\n" );
+ printreg(vsbe::PORE_PRV_BASE_ADDR0, "PORE_PRV_BASE_ADDR0 = 0x%llX\n" );
+ printreg(vsbe::PORE_PRV_BASE_ADDR1, "PORE_PRV_BASE_ADDR1 = 0x%llX\n" );
+ printreg(vsbe::PORE_OCI_MEMORY_BASE_ADDR0, "PORE_OCI_MEMORY_BASE_ADDR0 = 0x%llX\n" );
+ printreg(vsbe::PORE_OCI_MEMORY_BASE_ADDR1, "PORE_OCI_MEMORY_BASE_ADDR1 = 0x%llX\n" );
+ printreg(vsbe::PORE_TABLE_BASE_ADDR, "PORE_TABLE_BASE_ADDR = 0x%llX\n" );
+ printreg(vsbe::PORE_EXE_TRIGGER, "PORE_EXE_TRIGGER = 0x%llX\n" );
+ printreg(vsbe::PORE_SCRATCH0, "PORE_SCRATCH0 = 0x%llX\n" );
+ printreg(vsbe::PORE_SCRATCH1, "PORE_SCRATCH1 = 0x%llX\n" );
+ printreg(vsbe::PORE_SCRATCH2, "PORE_SCRATCH2 = 0x%llX\n" );
+ printreg(vsbe::PORE_IBUF_01, "PORE_IBUF_01 = 0x%llX\n" );
+ printreg(vsbe::PORE_IBUF_2, "PORE_IBUF_2 = 0x%llX\n" );
+ printreg(vsbe::PORE_DBG0, "PORE_DBG0 = 0x%llX\n" );
+ printreg(vsbe::PORE_DBG1, "PORE_DBG1 = 0x%llX\n" );
+ printreg(vsbe::PORE_PC_STACK0, "PORE_PC_STACK0 = 0x%llX\n" );
+ printreg(vsbe::PORE_PC_STACK1, "PORE_PC_STACK1 = 0x%llX\n" );
+ printreg(vsbe::PORE_PC_STACK2, "PORE_PC_STACK2 = 0x%llX\n" );
+ printreg(vsbe::PORE_ID_FLAGS, "PORE_ID_FLAGS = 0x%llX\n" );
+ printreg(vsbe::PORE_DATA0, "PORE_DATA0 = 0x%llX\n" );
+ printreg(vsbe::PORE_MEM_RELOC, "PORE_MEM_RELOC = 0x%llX\n" );
+ printreg(vsbe::PORE_I2C_E0_PARAM, "PORE_I2C_E0_PARAM = 0x%llX\n" );
+ printreg(vsbe::PORE_I2C_E1_PARAM, "PORE_I2C_E1_PARAM = 0x%llX\n" );
+ printreg(vsbe::PORE_I2C_E2_PARAM, "PORE_I2C_E2_PARAM = 0x%llX\n" );
+ printreg(vsbe::PORE_HIDDEN_STATE_0, "PORE_HIDDEN_STATE_0 = 0x%llX\n" );
+ printreg(vsbe::PORE_HIDDEN_STATE_1, "PORE_HIDDEN_STATE_1 = 0x%llX\n" );
+ printreg(vsbe::PORE_HIDDEN_STATE_2, "PORE_HIDDEN_STATE_2 = 0x%llX\n" );
+ printreg(vsbe::PORE_HIDDEN_STATE_3, "PORE_HIDDEN_STATE_3 = 0x%llX\n" );
+ printreg(vsbe::PORE_HIDDEN_STATE_4, "PORE_HIDDEN_STATE_4 = 0x%llX\n" );
+ } while (0);
+ stateArg->iv_data=p_state;
+ fclose( stateArg->iv_fd );
+ }
+
+#endif
+ if( me != ME_SUCCESS )
+ {
+ FAPI_ERR( "Model error extracting state. Errno(%i)\n", (int)me);
+ rc = 0xDEAD1600 | me;
+ }
+ } //if extract state
+
+ //----------------------------------------------------------------------
+ // Destroy PoreVe
+ //----------------------------------------------------------------------
+ delete poreve;
+
+ return rc;
+} //end function
+
+#ifdef FAPIECMD
+} //end extern C
+#endif
+
+/*
+*************** Do not edit this area ***************
+This section is automatically updated by CVS when you check in this file.
+Be sure to create CVS comments when you commit so that they are included here.
+
+$Log: fapiPoreVe.C,v $
+Revision 1.22 2012/01/09 20:55:27 jeshua
+Don't include file-related code for hostboot
+
+Revision 1.21 2011/12/07 22:30:46 jeshua
+Initial MRR support
+
+Revision 1.20 2011/11/17 18:17:59 jeshua
+Fixed state handling so it works with hostboot (hopefully)
+
+Revision 1.19 2011/11/02 23:24:44 bcbrock
+Changes required for portability to HBI environment
+
+Revision 1.18 2011/10/14 21:36:58 bcbrock
+Added an enumeration of hidden state variables for fapiPoreVe
+
+Revision 1.17 2011/10/06 19:29:34 jeshua
+Use poreve->getscom to check sbe vital
+
+Revision 1.16 2011/09/29 22:37:59 jeshua
+Fixed some copy-paste problems in the break point code
+Added a halt code check when the POREVE stops on a halt
+
+Revision 1.15 2011/09/08 16:03:28 jeshua
+Return an rc on an error_halt status
+
+Revision 1.14 2011/09/02 20:54:13 jeshua
+Open file for reading when installing state, close it after, open for writing when dumping state, close it after
+
+Revision 1.13 2011/09/02 19:57:06 jeshua
+Added state install and extract support
+
+Revision 1.12 2011/07/13 19:13:34 jeshua
+Enabled writing of the PNOR at John B's request
+
+Revision 1.11 2011/07/12 16:40:13 jeshua
+Breakpoint support
+
+Revision 1.10 2011/07/08 23:52:22 jeshua
+Updated for FAPI changes
+
+Revision 1.9 2011/07/07 20:33:32 jeshua
+Entry point is no longer in the hooks file
+
+Revision 1.8 2011/06/06 20:47:09 jeshua
+Removed workaround for setting the PC
+
+Revision 1.7 2011/06/03 19:49:55 jeshua
+Use the create funcion instead of new
+
+Revision 1.6 2011/06/03 14:51:13 jeshua
+Preliminary support for pdbg
+
+Revision 1.5 2011/05/24 19:34:07 jeshua
+Updated register read
+
+Revision 1.4 2011/05/23 16:24:49 jeshua
+Updated for new findGlobalSymbol signature
+
+Revision 1.3 2011/05/20 13:52:12 jeshua
+Fixed hook handling
+Added entryPoint handling
+
+Revision 1.2 2011/05/16 13:14:34 jeshua
+Updated comments
+Added hooks code from Bishop
+Renamed InstructionCountArg to OtherArg, and added PORE type into it
+Use bitwise AND when checking runStatus
+
+Revision 1.1 2011/05/11 19:57:29 jeshua
+Initial version
+
+
+
+
+*/
+/* Local Variables: */
+/* c-basic-offset: 4 */
+/* End: */
diff --git a/src/usr/pore/fapiporeve/fapiPoreVeArg.C b/src/usr/pore/fapiporeve/fapiPoreVeArg.C
new file mode 100644
index 000000000..43deb3499
--- /dev/null
+++ b/src/usr/pore/fapiporeve/fapiPoreVeArg.C
@@ -0,0 +1,265 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/fapiporeve/fapiPoreVeArg.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// -*- mode: C++; c-file-style: "linux"; -*-
+// $Id: fapiPoreVeArg.C,v 1.16 2012/01/09 20:55:57 jeshua Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/fapiPoreVeArg.C,v $
+//------------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2011
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//------------------------------------------------------------------------------
+// *! TITLE : fapiPoreVeArg.C
+// *! DESCRIPTION : Defines the arg struct to pass to fapiPoreVe
+// *! OWNER NAME : Jeshua Smith Email: jeshua@us.ibm.com
+// *! BACKUP NAME : John Bordovsky Email: johnb@us.ibm.com
+// #! ADDITIONAL COMMENTS :
+//
+//
+
+#include "fapiPoreVeArg.H"
+#include <fapi.H>
+
+#ifndef __HOSTBOOT_MODULE
+//For file mapping
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+//For hooks
+#include <dlfcn.h>
+#endif
+
+using namespace vsbe;
+
+FapiPoreVeArg::FapiPoreVeArg( const FapiPoreVeArg_t i_type ) :
+ iv_type(i_type)
+{
+}
+
+FapiPoreVeArg::~FapiPoreVeArg( )
+{
+}
+
+#ifndef __HOSTBOOT_MODULE
+FapiPoreVeMemArg::FapiPoreVeMemArg( const FapiPoreVeArg_t i_type,
+ const char* const i_filename,
+ const uint32_t i_base ) :
+ FapiPoreVeArg(i_type),
+ iv_base(i_base),
+ iv_filename(i_filename),
+ iv_fd(open(i_filename, O_RDONLY)),
+ iv_crcEnable(true)
+{
+ uint32_t rc = 0;
+
+ if( iv_fd < 0 ) {
+ FAPI_ERR( "Failed to open %s file\n", iv_filename );
+ rc = BAD_ERROR_CODE;
+ } else {
+ iv_size = lseek( iv_fd, 0, SEEK_END );
+ if( iv_size == (size_t)((off_t)-1) ) {
+ FAPI_ERR( "Failed to determine the size of %s file\n", iv_filename );
+ } else {
+ if( (iv_type == ARG_SRAM) || (iv_type == ARG_MAINMEM) ||
+ (iv_type == ARG_PNOR) || (iv_type == ARG_SEEPROM) ) {
+ iv_data = mmap( 0, iv_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, iv_fd, 0 );
+ } else {
+ iv_data = mmap( 0, iv_size, PROT_READ, MAP_PRIVATE, iv_fd, 0 );
+ }
+ if( iv_data == MAP_FAILED ) {
+ FAPI_ERR( "Failed to map %s file\n", iv_filename );
+ rc = BAD_ERROR_CODE;
+ }
+ }
+ }
+ //JDS TODO - how do I make the constructor fail if mapping failed?
+
+}
+#endif
+
+FapiPoreVeMemArg::FapiPoreVeMemArg( const FapiPoreVeArg_t i_type,
+ const uint32_t i_base,
+ const size_t i_size,
+ void * i_data) :
+ FapiPoreVeArg(i_type),
+ iv_base(i_base),
+#ifndef __HOSTBOOT_MODULE
+ iv_filename(NULL),
+ iv_fd(0),
+#endif
+ iv_size(i_size),
+ iv_crcEnable(true),
+ iv_data(i_data)
+{
+}
+
+FapiPoreVeMemArg::~FapiPoreVeMemArg( )
+{
+#ifndef __HOSTBOOT_MODULE
+ uint32_t rc = 0;
+ if( iv_data != NULL && iv_data != MAP_FAILED && iv_filename != NULL ) {
+ int unmap_rc = munmap( iv_data, iv_size );
+ if( unmap_rc != 0 ) {
+ FAPI_ERR( "Failed to unmap %s file\n", iv_filename );
+ rc = BAD_ERROR_CODE;
+ }
+ }
+ if( iv_fd >= 0 ) {
+ int close_rc = close( iv_fd );
+ if( close_rc != 0 ) {
+ FAPI_ERR( "Failed to close %s\n", iv_filename );
+ rc = BAD_ERROR_CODE;
+ }
+ }
+#endif
+ //JDS TODO - how do I make the destructor fail if unmapping failed?
+
+}
+
+#ifndef __HOSTBOOT_MODULE
+FapiPoreVeStateArg::FapiPoreVeStateArg( const char* const i_filename ) :
+ FapiPoreVeArg( ARG_STATE ),
+ iv_filename(i_filename),
+ iv_extractState(true),
+ iv_installState(true),
+ iv_data(NULL)
+{
+}
+#endif
+
+FapiPoreVeStateArg::FapiPoreVeStateArg( void * i_data ) :
+ FapiPoreVeArg( ARG_STATE ),
+#ifndef __HOSTBOOT_MODULE
+ iv_filename(NULL),
+#endif
+ iv_extractState(true),
+ iv_installState(true),
+ iv_data(i_data)
+{
+}
+
+FapiPoreVeStateArg::~FapiPoreVeStateArg( )
+{
+}
+
+FapiPoreVeHooksArg::FapiPoreVeHooksArg( const char* const i_filename ) :
+ FapiPoreVeArg( ARG_HOOKS ),
+ iv_filename(i_filename),
+ iv_handle(NULL)
+{
+}
+
+FapiPoreVeHooksArg::~FapiPoreVeHooksArg( )
+{
+#ifndef __HOSTBOOT_MODULE
+ if( iv_handle != NULL )
+ {
+ dlclose(iv_handle);
+ }
+#endif
+}
+
+FapiPoreVeOtherArg::FapiPoreVeOtherArg( const uint64_t i_instructionCount,
+ const PoreIbufId i_poreType ) :
+ FapiPoreVeArg( ARG_OTHER ),
+ iv_instructionCount(i_instructionCount),
+ iv_poreType(i_poreType),
+ iv_pdbgArgs(NULL),
+ iv_entryPoint(NULL),
+ iv_breakpoint(NULL),
+ iv_mrr(0)
+{
+}
+
+FapiPoreVeOtherArg::~FapiPoreVeOtherArg( )
+{
+}
+
+
+/*
+*************** Do not edit this area ***************
+This section is automatically updated by CVS when you check in this file.
+Be sure to create CVS comments when you commit so that they are included here.
+
+$Log: fapiPoreVeArg.C,v $
+Revision 1.16 2012/01/09 20:55:57 jeshua
+Don't include file-related code for hostboot
+
+Revision 1.15 2011/12/07 22:30:59 jeshua
+Initial MRR support
+
+Revision 1.14 2011/12/02 16:12:11 jeshua
+Make seeprom writable (for control bits)
+
+Revision 1.13 2011/11/17 18:20:05 jeshua
+Skip file handling for hostboot
+
+Revision 1.12 2011/09/20 15:38:42 jeshua
+Allow creating memory args from memory pointers instead of just files
+
+Revision 1.11 2011/09/02 20:54:29 jeshua
+No longer do file open and close
+
+Revision 1.10 2011/09/02 20:01:04 jeshua
+Fixes for state arg support
+
+Revision 1.9 2011/07/13 19:13:43 jeshua
+Enabled writing of the PNOR at John B's request
+
+Revision 1.8 2011/07/12 16:39:38 jeshua
+Breakpoint support
+
+Revision 1.7 2011/07/08 23:53:16 jeshua
+Updated for FAPI changes
+
+Revision 1.6 2011/07/07 20:34:43 jeshua
+Moved entry point from hooks to other arg
+
+Revision 1.5 2011/06/03 15:38:50 jeshua
+Added pdbgArg to OtherArg type
+
+Revision 1.4 2011/05/20 14:05:10 jeshua
+Don't close hooks file if it wasn't opened
+
+Revision 1.3 2011/05/20 13:57:48 jeshua
+Added const
+Use initializers
+Unload hooks on destruction
+
+Revision 1.2 2011/05/13 21:19:42 jeshua
+Updated comments
+Renamed InstructionCountArg to OtherArg, and added PORE type into it
+Added iv_extractState
+Added Hooks class
+
+Revision 1.1 2011/05/11 19:57:29 jeshua
+Initial version
+
+
+
+
+*/
+/* Local Variables: */
+/* c-basic-offset: 4 */
+/* End: */
diff --git a/src/usr/pore/fapiporeve/fapiPoreVeArg.H b/src/usr/pore/fapiporeve/fapiPoreVeArg.H
new file mode 100644
index 000000000..8b2b0a9a8
--- /dev/null
+++ b/src/usr/pore/fapiporeve/fapiPoreVeArg.H
@@ -0,0 +1,197 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/fapiporeve/fapiPoreVeArg.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// -*- mode: C++; c-file-style: "linux"; -*-
+// $Id: fapiPoreVeArg.H,v 1.11 2011/12/07 22:31:39 jeshua Exp $
+// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/fapiPoreVeArg.H,v $
+//------------------------------------------------------------------------------
+// *! (C) Copyright International Business Machines Corp. 2011
+// *! All Rights Reserved -- Property of IBM
+// *! *** IBM Confidential ***
+//------------------------------------------------------------------------------
+// *! TITLE : fapiPoreVeArg.H
+// *! DESCRIPTION : Headers for the args to pass to fapiPoreVe
+// *! OWNER NAME : Jeshua Smith Email: jeshua@us.ibm.com
+// *! BACKUP NAME : John Bordovsky Email: johnb@us.ibm.com
+// #! ADDITIONAL COMMENTS :
+//
+//
+
+#ifndef __FAPIPOREVEARG_H
+#define __FAPIPOREVEARG_H
+
+#include "poreconstants.H"
+
+namespace vsbe
+{
+
+ enum FapiPoreVeArg_t
+ {
+ ARG_STATE,
+ ARG_OTHER,
+ ARG_HOOKS,
+ ARG_OTPROM,
+ ARG_PNOR,
+ ARG_SEEPROM,
+ ARG_SRAM,
+ ARG_MAINMEM,
+ };
+
+ const uint32_t BAD_ERROR_CODE = 0xDEADC0DE;
+
+ struct FapiPoreVeArg
+ {
+ public:
+ FapiPoreVeArg( const FapiPoreVeArg_t i_type );
+
+ virtual ~FapiPoreVeArg();
+
+ const FapiPoreVeArg_t iv_type;
+ };
+
+ struct FapiPoreVeMemArg : public FapiPoreVeArg
+ {
+ public:
+#ifndef __HOSTBOOT_MODULE
+ FapiPoreVeMemArg( const FapiPoreVeArg_t i_type,
+ const char* const i_filename,
+ const uint32_t i_base );
+#endif
+ FapiPoreVeMemArg( const FapiPoreVeArg_t i_type,
+ const uint32_t i_base,
+ const size_t i_size,
+ void * i_data );
+
+ ~FapiPoreVeMemArg();
+
+ const uint32_t iv_base;
+#ifndef __HOSTBOOT_MODULE
+ const char* iv_filename;
+ const int iv_fd;
+#endif
+ size_t iv_size;
+ bool iv_crcEnable;
+ void * iv_data;
+ };
+
+ struct FapiPoreVeStateArg : public FapiPoreVeArg
+ {
+ public:
+#ifndef __HOSTBOOT_MODULE
+ FapiPoreVeStateArg( const char* const i_filename );
+#endif
+ FapiPoreVeStateArg( void * i_data );
+
+ virtual ~FapiPoreVeStateArg();
+
+#ifndef __HOSTBOOT_MODULE
+ const char* const iv_filename;
+ FILE * iv_fd;
+#endif
+ bool iv_extractState;
+ bool iv_installState;
+ void * iv_data;
+ };
+
+ struct FapiPoreVeHooksArg : public FapiPoreVeArg
+ {
+ public:
+ FapiPoreVeHooksArg( const char* const i_filename );
+
+ virtual ~FapiPoreVeHooksArg();
+
+ const char* const iv_filename;
+ void* iv_handle;
+ };
+
+ struct FapiPoreVeOtherArg : public FapiPoreVeArg
+ {
+ public:
+ FapiPoreVeOtherArg( const uint64_t i_instructionCount,
+ const PoreIbufId i_poreType );
+
+ virtual ~FapiPoreVeOtherArg();
+
+ uint64_t iv_instructionCount;
+ PoreIbufId iv_poreType;
+ const char* iv_pdbgArgs;
+ char* iv_entryPoint;
+ char* iv_breakpoint;
+ uint64_t iv_mrr;
+ };
+} //end vsbe namespace
+
+#endif
+
+/*
+*************** Do not edit this area ***************
+This section is automatically updated by CVS when you check in this file.
+Be sure to create CVS comments when you commit so that they are included here.
+
+$Log: fapiPoreVeArg.H,v $
+Revision 1.11 2011/12/07 22:31:39 jeshua
+Initial MRR support
+
+Revision 1.10 2011/11/17 18:21:10 jeshua
+Skip file handling for hostboot
+Keep a pointer to raw state data in the state arg
+
+Revision 1.9 2011/09/20 15:39:06 jeshua
+Allow creating memory args from pointers instead of just files
+
+Revision 1.8 2011/09/02 19:57:45 jeshua
+Updates for state install & extract support
+
+Revision 1.7 2011/08/03 23:01:47 bcbrock
+Update fapiPoreVeArg.H to use the new 'poreconstants.H'
+
+Revision 1.6 2011/07/12 16:39:39 jeshua
+Breakpoint support
+
+Revision 1.5 2011/07/07 20:34:59 jeshua
+Moved entry point from hooks to other arg
+
+Revision 1.4 2011/06/03 15:38:04 jeshua
+Added pdbgArgs to OtherArg type
+
+Revision 1.3 2011/05/20 13:54:51 jeshua
+Changed to struct
+Added const
+Added entryPoint
+Removed dead code
+
+Revision 1.2 2011/05/13 21:15:22 jeshua
+Updated comments
+Renamed InstructionCountArg to OtherArg, and added PORE type into it
+Added iv_extractState
+Added Hooks class
+
+Revision 1.1 2011/05/11 19:57:30 jeshua
+Initial version
+
+
+
+
+*/
+/* Local Variables: */
+/* c-basic-offset: 4 */
+/* End: */
diff --git a/src/usr/pore/fapiporeve/makefile b/src/usr/pore/fapiporeve/makefile
new file mode 100644
index 000000000..b83666c75
--- /dev/null
+++ b/src/usr/pore/fapiporeve/makefile
@@ -0,0 +1,39 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/pore/fapiporeve/makefile $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2011
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or other-
+# wise divested of its trade secrets, irrespective of what has
+# been deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END
+
+ROOTPATH = ../../../..
+# fapiporeve provides interfaces to create a poreve object
+# with a set of pre-defined arguments
+MODULE = fapiporeve
+
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/ecmddatabuffer
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/fapi
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/plat
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/hwp
+EXTRAINCDIR += ${ROOTPATH}/src/usr/pore/poreve/porevesrc
+EXTRAINCDIR += ${ROOTPATH}/src/usr/pore/poreve/pore_model
+EXTRAINCDIR += ${ROOTPATH}/src/usr/pore/poreve/model
+
+OBJS = fapiPoreVe.o fapiPoreVeArg.o
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/pore/makefile b/src/usr/pore/makefile
new file mode 100644
index 000000000..c544e8efb
--- /dev/null
+++ b/src/usr/pore/makefile
@@ -0,0 +1,27 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/xscom/makefile $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2011
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or other-
+# wise divested of its trade secrets, irrespective of what has
+# been deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END
+ROOTPATH = ../../..
+
+SUBDIRS = fapiporeve.d poreve.d test.d
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/pore/poreve/hook/sbe_pnor.hooks.cc b/src/usr/pore/poreve/hook/sbe_pnor.hooks.cc
new file mode 100755
index 000000000..082f7d672
--- /dev/null
+++ b/src/usr/pore/poreve/hook/sbe_pnor.hooks.cc
@@ -0,0 +1,798 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/hook/sbe_pnor.hooks.cc $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// $Id$
+//
+// File generated by hook_indexer
+// Arguments : -g -b bin/sbe_pnor.out -c bin/sbe_pnor.hooks.cc -m pnor
+// Generation Date : Thu Jan 12 17:14:04 EST 2012
+
+#include "hookmanager.H"
+
+using namespace vsbe;
+
+static const char* symbols[374] = {
+"oci::sbe_pnor_error_2_control",
+"oci::slw_error_2_ptr",
+"oci::proc_sbe_instruct_start_winkle_return",
+"pnor::slw_deep_winkle_exit_ptr",
+"oci::sbe_pnor_undefined_ptr",
+"pnor::return_from_proc_sbe_select_ex",
+"pnor::proc_sbe_ex_host_runtime_scom_control",
+"pnor::return_from_slw_deep_winkle_enter",
+"pnor::proc_sbe_ex_chiplet_reset_control",
+"oci::proc_sbe_ex_host_runtime_scom",
+"pnor::slw_undefined",
+"pnor::_sbe_pnor_halt",
+"oci::proc_sbe_pnor_setup_control",
+"pnor::sbe_pnor_error_3_ptr",
+"pnor::return_from_slw_deep_sleep_enter",
+"oci::proc_sbe_ex_func_l3_ring_loc",
+"pnor::return_from_proc_sbe_ex_core_initf",
+"pnor::proc_sbe_ex_startclocks_control",
+"oci::return_from_slw_deep_winkle_enter",
+"oci::proc_sbe_ex_chiplet_reset_control",
+"pnor::proc_sbe_ex_enable_edram_control",
+"pnor::proc_sbe_ex_sp_runtime_scom_control",
+"oci::proc_slw_prolog",
+"pnor::sbe_pnor_error_1_control",
+"oci::proc_sbe_ex_startclocks",
+"oci::return_from_slw_fast_sleep_exit",
+"oci::proc_sbe_ex_sp_runtime_scom",
+"oci::slw_power_on_off",
+"pnor::slw_fast_sleep_exit",
+"pnor::slw_error_1_ptr",
+"pnor::proc_sbe_ex_repair_initf",
+"pnor::slw_fast_sleep_enter_ptr",
+"pnor::sbe_pnor_undefined_ptr",
+"oci::proc_sbe_ex_core_initf",
+"pnor::exit_ex_scan0_module",
+"pnor::sbe_pnor_undefined",
+"pnor::host_runtime_scom",
+"pnor::proc_sbe_ex_initf",
+"pnor::slw_pfet_seq",
+"pnor::slw_fast_sleep_exit_control",
+"pnor::proc_sbe_ex_repair_initf_control",
+"pnor::slw_fast_winkle_enter_ptr",
+"pnor::proc_sbe_ring_table_pnor_loc",
+"pnor::slw_error_1_control",
+"oci::proc_sbe_dd10_ex_func_core_ring",
+"pnor::return_from_proc_sbe_instruct_start",
+"oci::proc_sbe_ex_core_gptr_time_initf",
+"oci::proc_sbe_instruct_start_sleep_return",
+"pnor::slw_fast_winkle_enter",
+"pnor::proc_sbe_ex_pll_initf_control",
+"oci::slw_error_0",
+"pnor::slw_branch_table",
+"oci::slw_error_1",
+"oci::slw_error_2",
+"oci::slw_error_3",
+"pnor::slw_deep_sleep_enter_ptr",
+"pnor::sbe_pnor_error_0_ptr",
+"pnor::return_from_proc_sbe_pnor_setup",
+"oci::slw_error_4",
+"oci::host_runtime_scom",
+"oci::proc_sbe_ex_initf",
+"oci::proc_sbe_ex_core_gptr_time_initf_control",
+"pnor::proc_slw_epilog",
+"oci::slw_fast_winkle_enter_ptr",
+"pnor::proc_sbe_ex_core_initf",
+"pnor::return_from_proc_sbe_ex_pll_initf",
+"oci::slw_error_2_control",
+"pnor::return_from_proc_sbe_ex_initf",
+"pnor::proc_sbe_instruct_start",
+"oci::proc_sbe_ex_core_repair_initf",
+"oci::proc_sbe_ex_gptr_time_initf",
+"pnor::proc_sbe_start_host_deadman_timer",
+"oci::return_from_proc_sbe_pb_startclocks",
+"pnor::proc_sbe_dd10_ex_func_l3_ring",
+"pnor::proc_sbe_ex_occ_runtime_scom",
+"oci::proc_sbe_ex_do_manual_inits",
+"oci::sp_runtime_scom",
+"oci::sbe_pnor_error_3_ptr",
+"oci::proc_sbe_run_exinit_sleep_return",
+"oci::return_from_proc_sbe_ex_pll_initf",
+"oci::proc_sbe_ex_core_repair_initf_control",
+"oci::proc_sbe_ex_gptr_time_initf_control",
+"pnor::proc_sbe_start_host_deadman_timer_control",
+"pnor::proc_sbe_ex_chiplet_reset",
+"pnor::proc_sbe_pnor_setup_control",
+"oci::proc_sbe_start_host_deadman_timer",
+"oci::slw_fast_sleep_exit_ptr",
+"oci::slw_deep_winkle_enter",
+"pnor::return_from_proc_sbe_ex_arrayinit",
+"pnor::ex_scan0_module",
+"oci::sbe_pnor_error_3_control",
+"oci::proc_sbe_ex_arrayinit_control",
+"oci::proc_sbe_pnor_setup",
+"pnor::return_from_proc_sbe_start_host_deadman_timer",
+"oci::slw_error_4_ptr",
+"oci::exit_ex_scan0_module",
+"pnor::_sbe_pnor_start",
+"oci::proc_sbe_start_host_deadman_timer_control",
+"oci::proc_sbe_pb_startclocks_control",
+"oci::proc_sbe_ex_chiplet_reset",
+"pnor::proc_sbe_ex_enable_edram",
+"pnor::proc_sbe_ex_sp_runtime_scom",
+"oci::slw_pfet_seq",
+"pnor::slw_control_vector",
+"oci::return_from_proc_sbe_ex_arrayinit",
+"oci::proc_sbe_ring_table_pnor_loc",
+"pnor::return_from_proc_sbe_ex_host_runtime_scom",
+"oci::proc_sbe_ring_table_pnor",
+"oci::sbe_pnor_error_0_ptr",
+"pnor::sbe_pnor_error_2_control",
+"pnor::return_from_proc_sbe_run_exinit",
+"pnor::slw_error_3_ptr",
+"pnor::slw_error_0",
+"pnor::return_from_slw_deep_sleep_exit",
+"pnor::host_image_offset",
+"pnor::slw_error_1",
+"pnor::return_from_proc_sbe_ex_dpll_initf",
+"pnor::slw_error_2",
+"oci::return_from_proc_sbe_ex_host_runtime_scom",
+"pnor::slw_error_3",
+"oci::proc_sbe_ex_startclocks_control",
+"oci::return_from_proc_sbe_ex_chiplet_reset",
+"pnor::slw_error_4",
+"oci::slw_undefined_control",
+"oci::proc_sbe_fabricinit_control",
+"oci::slw_load_sprg0",
+"oci::proc_sbe_ex_occ_runtime_scom",
+"pnor::slw_error_2_control",
+"oci::slw_error_1_ptr",
+"pnor::proc_sbe_select_ex",
+"pnor::sbe_pnor_undefined_control",
+"oci::proc_sbe_ex_dpll_initf",
+"oci::host_image_offset",
+"oci::return_from_proc_sbe_ex_init_escape",
+"pnor::return_from_proc_sbe_lco_loader",
+"oci::return_from_slw_fast_winkle_exit",
+"pnor::sbe_pnor_branch_table",
+"pnor::proc_sbe_ex_gptr_time_initf",
+"pnor::return_from_proc_sbe_pb_startclocks",
+"oci::proc_sbe_ex_pll_initf",
+"pnor::proc_sbe_ex_do_manual_inits",
+"pnor::return_from_proc_sbe_ex_chiplet_init",
+"pnor::sbe_pnor_error_2_ptr",
+"pnor::slw_power_on_off",
+"pnor::proc_sbe_select_ex_control",
+"pnor::slw_fast_winkle_enter_control",
+"pnor::proc_sbe_ex_gptr_time_initf_control",
+"oci::slw_error_3_control",
+"oci::proc_sbe_run_exinit",
+"pnor::slw_load_sprg0",
+"oci::slw_deep_sleep_exit",
+"oci::return_from_proc_sbe_pnor_setup",
+"pnor::proc_sbe_pb_startclocks",
+"pnor::slw_error_0_ptr",
+"pnor::return_from_slw_fast_winkle_enter",
+"oci::return_from_slw_deep_winkle_exit",
+"pnor::proc_sbe_pnor_setup",
+"oci::sbe_pnor_error_0",
+"pnor::proc_sbe_ex_core_gptr_time_initf",
+"oci::proc_slw_epilog",
+"pnor::slw_fast_winkle_exit",
+"oci::sbe_pnor_error_1",
+"pnor::proc_sbe_ex_dpll_initf",
+"pnor::proc_sbe_instruct_start_control",
+"pnor::proc_sbe_instruct_start_winkle_return",
+"oci::sbe_pnor_error_2",
+"pnor::return_from_proc_sbe_ex_core_gptr_time_initf",
+"pnor::return_from_proc_sbe_ex_core_repair_initf",
+"oci::sbe_pnor_error_3",
+"oci::proc_sbe_ex_arrayinit",
+"oci::slw_deep_sleep_exit_control",
+"oci::sbe_pnor_error_4",
+"oci::return_from_proc_sbe_ex_core_initf",
+"pnor::proc_sbe_ex_occ_runtime_scom_control",
+"oci::proc_sbe_instruct_start",
+"pnor::return_from_proc_sbe_ex_sp_runtime_scom",
+"pnor::return_from_proc_sbe_fabricinit",
+"pnor::proc_sbe_ex_host_runtime_scom",
+"oci::sbe_pnor_error_0_control",
+"pnor::proc_sbe_ex_core_gptr_time_initf_control",
+"oci::proc_sbe_lco_loader",
+"oci::occ_runtime_scom",
+"oci::return_from_slw_fast_winkle_enter",
+"oci::sbe_pnor_error_4_control",
+"pnor::slw_deep_sleep_exit_ptr",
+"oci::return_from_proc_sbe_ex_core_repair_initf",
+"oci::return_from_proc_sbe_ex_startclocks",
+"oci::proc_sbe_lco_loader_control",
+"pnor::slw_deep_winkle_exit",
+"oci::slw_deep_winkle_enter_control",
+"oci::sbe_pnor_undefined",
+"pnor::return_from_slw_error_0",
+"pnor::proc_sbe_run_exinit_sleep_return",
+"pnor::return_from_slw_error_1",
+"pnor::return_from_slw_error_2",
+"oci::ex_scan0_module",
+"pnor::return_from_slw_error_3",
+"pnor::return_from_slw_error_4",
+"oci::proc_sbe_ex_host_runtime_scom_control",
+"pnor::proc_sbe_fabricinit_control",
+"oci::proc_sbe_ex_chiplet_init",
+"oci::_sbe_pnor_start",
+"oci::return_from_proc_sbe_ex_chiplet_init",
+"oci::slw_undefined",
+"pnor::sbe_pnor_error_3_control",
+"oci::sbe_pnor_error_2_ptr",
+"oci::proc_sbe_fabricinit",
+"pnor::return_from_proc_sbe_ex_gptr_time_initf",
+"pnor::return_from_proc_sbe_ex_init_escape",
+"pnor::return_from_proc_sbe_ex_repair_initf",
+"oci::proc_sbe_ex_chiplet_init_control",
+"pnor::return_from_proc_sbe_ex_do_manual_inits",
+"oci::slw_fast_winkle_exit_ptr",
+"oci::proc_sbe_ex_core_initf_control",
+"oci::return_from_proc_sbe_run_exinit",
+"oci::return_from_proc_sbe_ex_occ_runtime_scom",
+"oci::slw_fast_winkle_exit",
+"pnor::slw_error_3_control",
+"pnor::proc_sbe_ring_table_pnor",
+"pnor::proc_sbe_run_exinit",
+"oci::slw_error_3_ptr",
+"oci::return_from_slw_deep_sleep_exit",
+"pnor::proc_sbe_ex_initf_control",
+"oci::return_from_proc_sbe_ex_core_gptr_time_initf",
+"pnor::slw_deep_sleep_exit",
+"pnor::proc_sbe_ex_core_repair_initf",
+"pnor::proc_sbe_ex_init_escape",
+"oci::proc_sbe_ex_occ_runtime_scom_control",
+"oci::return_from_slw_fast_sleep_enter",
+"oci::return_from_sbe_pnor_undefined",
+"pnor::sbe_pnor_error_4_ptr",
+"oci::proc_sbe_ex_dpll_initf_control",
+"pnor::proc_sbe_run_exinit_winkle_return",
+"oci::slw_error_0_control",
+"pnor::slw_deep_sleep_exit_control",
+"pnor::proc_sbe_ex_core_repair_initf_control",
+"oci::proc_sbe_ex_func_core_ring_loc",
+"pnor::proc_sbe_ex_init_escape_control",
+"oci::slw_fast_winkle_enter",
+"oci::proc_sbe_ex_pll_initf_control",
+"oci::slw_error_4_control",
+"oci::slw_deep_winkle_exit_ptr",
+"pnor::slw_deep_winkle_enter_ptr",
+"oci::proc_sbe_ex_initf_control",
+"oci::return_from_proc_sbe_lco_loader",
+"pnor::proc_sbe_lco_loader",
+"oci::slw_deep_winkle_exit",
+"pnor::slw_deep_winkle_enter",
+"pnor::proc_sbe_ex_core_initf_control",
+"pnor::proc_sbe_ex_arrayinit_control",
+"oci::slw_control_vector",
+"pnor::slw_error_2_ptr",
+"oci::proc_sbe_run_exinit_control",
+"oci::proc_sbe_run_exinit_winkle_return",
+"oci::return_from_slw_deep_sleep_enter",
+"pnor::return_from_slw_fast_winkle_exit",
+"pnor::return_from_proc_sbe_ex_startclocks",
+"pnor::slw_fast_sleep_enter",
+"pnor::proc_sbe_lco_loader_control",
+"oci::return_from_proc_sbe_ex_initf",
+"oci::slw_deep_winkle_enter_ptr",
+"oci::proc_sbe_ex_do_manual_inits_control",
+"pnor::return_from_sbe_pnor_undefined",
+"oci::proc_sbe_ex_enable_edram_control",
+"pnor::slw_fast_winkle_exit_control",
+"oci::sbe_pnor_error_1_control",
+"oci::proc_sbe_dd10_ex_func_l3_ring",
+"oci::find_ddX_ring_image",
+"pnor::proc_sbe_ex_dpll_initf_control",
+"oci::proc_sbe_pb_startclocks",
+"oci::slw_error_0_ptr",
+"pnor::slw_fast_sleep_enter_control",
+"pnor::proc_sbe_ex_func_core_ring_loc",
+"oci::proc_sbe_ex_repair_initf",
+"oci::slw_fast_sleep_enter_ptr",
+"pnor::sbe_pnor_branch_table_loc",
+"oci::proc_sbe_instruct_start_control",
+"oci::return_from_proc_sbe_ex_repair_initf",
+"pnor::proc_slw_prolog",
+"oci::return_from_proc_sbe_ex_dpll_initf",
+"pnor::slw_undefined_ptr",
+"pnor::proc_sbe_ex_startclocks",
+"oci::return_from_proc_sbe_ex_sp_runtime_scom",
+"oci::return_from_proc_sbe_fabricinit",
+"pnor::sbe_pnor_error_1_ptr",
+"pnor::return_from_slw_fast_sleep_exit",
+"pnor::return_from_slw_deep_winkle_exit",
+"pnor::proc_sbe_fabricinit",
+"pnor::slw_deep_sleep_enter",
+"pnor::sbe_pnor_error_0",
+"oci::proc_sbe_ex_repair_initf_control",
+"pnor::sbe_pnor_error_1",
+"pnor::return_from_proc_sbe_ex_enable_edram",
+"pnor::sbe_pnor_error_2",
+"pnor::return_from_sbe_pnor_error_0",
+"pnor::sbe_pnor_error_3",
+"pnor::return_from_sbe_pnor_error_1",
+"pnor::sbe_pnor_error_4",
+"pnor::return_from_sbe_pnor_error_2",
+"oci::proc_sbe_select_ex",
+"pnor::slw_deep_winkle_exit_control",
+"oci::slw_deep_sleep_exit_ptr",
+"oci::sbe_pnor_undefined_control",
+"oci::sbe_pnor_branch_table_loc",
+"pnor::return_from_sbe_pnor_error_3",
+"pnor::return_from_proc_sbe_ex_chiplet_reset",
+"oci::slw_branch_table",
+"pnor::return_from_sbe_pnor_error_4",
+"oci::return_from_proc_sbe_start_host_deadman_timer",
+"pnor::slw_undefined_control",
+"oci::slw_undefined_ptr",
+"pnor::slw_deep_sleep_enter_control",
+"pnor::sbe_pnor_error_0_control",
+"oci::slw_deep_sleep_enter_ptr",
+"pnor::occ_runtime_scom",
+"pnor::proc_sbe_dd10_ex_func_core_ring",
+"pnor::sbe_pnor_error_4_control",
+"oci::return_from_slw_error_0",
+"oci::proc_sbe_select_ex_control",
+"oci::sbe_pnor_error_4_ptr",
+"oci::return_from_slw_error_1",
+"oci::return_from_slw_error_2",
+"oci::return_from_slw_error_3",
+"oci::return_from_slw_error_4",
+"pnor::return_from_slw_undefined",
+"pnor::proc_sbe_ex_pll_initf",
+"oci::proc_sbe_ex_sp_runtime_scom_control",
+"pnor::slw_error_0_control",
+"pnor::proc_sbe_ex_func_l3_ring_loc",
+"oci::slw_fast_sleep_exit",
+"pnor::slw_error_4_control",
+"oci::return_from_proc_sbe_ex_gptr_time_initf",
+"oci::slw_fast_sleep_enter",
+"pnor::proc_sbe_ex_chiplet_init",
+"oci::ex_init_escape",
+"oci::return_from_proc_sbe_ex_do_manual_inits",
+"oci::return_from_slw_undefined",
+"pnor::sp_runtime_scom",
+"oci::slw_fast_sleep_exit_control",
+"oci::slw_fast_winkle_exit_control",
+"pnor::proc_sbe_run_exinit_control",
+"oci::slw_error_1_control",
+"pnor::proc_sbe_ex_arrayinit",
+"oci::return_from_proc_sbe_instruct_start",
+"oci::slw_fast_sleep_enter_control",
+"pnor::proc_sbe_ex_chiplet_init_control",
+"oci::return_from_proc_sbe_select_ex",
+"pnor::proc_sbe_ex_do_manual_inits_control",
+"oci::sbe_pnor_branch_table",
+"oci::proc_sbe_ex_init_escape",
+"pnor::slw_fast_sleep_exit_ptr",
+"pnor::find_ddX_ring_image",
+"pnor::slw_fast_winkle_exit_ptr",
+"oci::sbe_pnor_error_1_ptr",
+"oci::_sbe_pnor_halt",
+"oci::proc_sbe_ex_enable_edram",
+"pnor::return_from_proc_sbe_ex_occ_runtime_scom",
+"oci::slw_deep_sleep_enter",
+"pnor::proc_sbe_instruct_start_sleep_return",
+"oci::slw_fast_winkle_enter_control",
+"oci::return_from_proc_sbe_ex_enable_edram",
+"oci::return_from_sbe_pnor_error_0",
+"pnor::slw_error_4_ptr",
+"oci::return_from_sbe_pnor_error_1",
+"oci::return_from_sbe_pnor_error_2",
+"pnor::ex_init_escape",
+"oci::proc_sbe_ex_init_escape_control",
+"oci::slw_deep_winkle_exit_control",
+"pnor::slw_deep_winkle_enter_control",
+"oci::return_from_sbe_pnor_error_3",
+"pnor::return_from_slw_fast_sleep_enter",
+"oci::return_from_sbe_pnor_error_4",
+"pnor::proc_sbe_pb_startclocks_control",
+"oci::slw_deep_sleep_enter_control",
+};
+
+static GlobalSymbolInfo info[374] = {
+{PoreAddress(0x8000, 0x80000290), 'R'},
+{PoreAddress(0x8000, 0x80001ea8), 'T'},
+{PoreAddress(0x8000, 0x800019ac), 'T'},
+{PoreAddress(0x800b, 0x800016c4), 'T'},
+{PoreAddress(0x8000, 0x800078a8), 'T'},
+{PoreAddress(0x800b, 0x80004b3c), 'T'},
+{PoreAddress(0x800b, 0x80000218), 'R'},
+{PoreAddress(0x800b, 0x80001594), 'T'},
+{PoreAddress(0x800b, 0x80000170), 'R'},
+{PoreAddress(0x8000, 0x80000834), 'T'},
+{PoreAddress(0x800b, 0x80002550), 'T'},
+{PoreAddress(0x800b, 0x800051d4), 'T'},
+{PoreAddress(0x8000, 0x800002b0), 'R'},
+{PoreAddress(0x800b, 0x800075d0), 'T'},
+{PoreAddress(0x800b, 0x800011e4), 'T'},
+{PoreAddress(0x8000, 0x80000120), 'R'},
+{PoreAddress(0x800b, 0x8000665c), 'T'},
+{PoreAddress(0x800b, 0x800001d8), 'R'},
+{PoreAddress(0x8000, 0x80001594), 'T'},
+{PoreAddress(0x8000, 0x80000170), 'R'},
+{PoreAddress(0x800b, 0x800001b8), 'R'},
+{PoreAddress(0x800b, 0x800001f8), 'R'},
+{PoreAddress(0x8000, 0x8000095c), 'T'},
+{PoreAddress(0x800b, 0x80000288), 'R'},
+{PoreAddress(0x8000, 0x800006d4), 'T'},
+{PoreAddress(0x8000, 0x80000c5c), 'T'},
+{PoreAddress(0x8000, 0x800007dc), 'T'},
+{PoreAddress(0x8000, 0x80002558), 'T'},
+{PoreAddress(0x800b, 0x800018cc), 'T'},
+{PoreAddress(0x800b, 0x80001d08), 'T'},
+{PoreAddress(0x800b, 0x800004a0), 'T'},
+{PoreAddress(0x800b, 0x800009dc), 'T'},
+{PoreAddress(0x800b, 0x800078a8), 'T'},
+{PoreAddress(0x8000, 0x80000678), 'T'},
+{PoreAddress(0x800b, 0x80000488), 'T'},
+{PoreAddress(0x800b, 0x80007a28), 'T'},
+{PoreAddress(0x800b, 0x80000210), 'R'},
+{PoreAddress(0x800b, 0x80000620), 'T'},
+{PoreAddress(0x800b, 0x8000272c), 'T'},
+{PoreAddress(0x800b, 0x800002d0), 'R'},
+{PoreAddress(0x800b, 0x80000190), 'R'},
+{PoreAddress(0x800b, 0x80000d8c), 'T'},
+{PoreAddress(0x800b, 0x80000100), 'R'},
+{PoreAddress(0x800b, 0x80000308), 'R'},
+{PoreAddress(0x8000, 0x80000228), 'R'},
+{PoreAddress(0x800b, 0x80004f74), 'T'},
+{PoreAddress(0x8000, 0x800005c8), 'T'},
+{PoreAddress(0x8000, 0x80001910), 'T'},
+{PoreAddress(0x800b, 0x80001938), 'T'},
+{PoreAddress(0x800b, 0x80000180), 'R'},
+{PoreAddress(0x8000, 0x80002528), 'T'},
+{PoreAddress(0x800b, 0x80000860), 'T'},
+{PoreAddress(0x8000, 0x80002530), 'T'},
+{PoreAddress(0x8000, 0x80002538), 'T'},
+{PoreAddress(0x8000, 0x80002540), 'T'},
+{PoreAddress(0x800b, 0x8000113c), 'T'},
+{PoreAddress(0x800b, 0x8000718c), 'T'},
+{PoreAddress(0x800b, 0x80004704), 'T'},
+{PoreAddress(0x8000, 0x80002548), 'T'},
+{PoreAddress(0x8000, 0x80000210), 'R'},
+{PoreAddress(0x8000, 0x80000620), 'T'},
+{PoreAddress(0x8000, 0x800001b0), 'R'},
+{PoreAddress(0x800b, 0x8000099c), 'T'},
+{PoreAddress(0x8000, 0x80000d8c), 'T'},
+{PoreAddress(0x800b, 0x80000678), 'T'},
+{PoreAddress(0x800b, 0x80005c4c), 'T'},
+{PoreAddress(0x8000, 0x80000310), 'R'},
+{PoreAddress(0x800b, 0x800064f4), 'T'},
+{PoreAddress(0x800b, 0x8000702c), 'T'},
+{PoreAddress(0x8000, 0x800004a4), 'T'},
+{PoreAddress(0x8000, 0x800005c4), 'T'},
+{PoreAddress(0x800b, 0x80007028), 'T'},
+{PoreAddress(0x8000, 0x8000486c), 'T'},
+{PoreAddress(0x800b, 0x80000250), 'R'},
+{PoreAddress(0x800b, 0x80000808), 'T'},
+{PoreAddress(0x8000, 0x800006d0), 'T'},
+{PoreAddress(0x8000, 0x800001f0), 'R'},
+{PoreAddress(0x8000, 0x800075d0), 'T'},
+{PoreAddress(0x8000, 0x8000190c), 'T'},
+{PoreAddress(0x8000, 0x80005c4c), 'T'},
+{PoreAddress(0x8000, 0x80000198), 'R'},
+{PoreAddress(0x8000, 0x800001a8), 'R'},
+{PoreAddress(0x800b, 0x80000168), 'R'},
+{PoreAddress(0x800b, 0x80000380), 'T'},
+{PoreAddress(0x800b, 0x800002b0), 'R'},
+{PoreAddress(0x8000, 0x80007028), 'T'},
+{PoreAddress(0x8000, 0x80000bb4), 'T'},
+{PoreAddress(0x8000, 0x80001940), 'T'},
+{PoreAddress(0x800b, 0x80006208), 'T'},
+{PoreAddress(0x800b, 0x80000414), 'T'},
+{PoreAddress(0x8000, 0x80000298), 'R'},
+{PoreAddress(0x8000, 0x800001a0), 'R'},
+{PoreAddress(0x8000, 0x80007a2c), 'T'},
+{PoreAddress(0x800b, 0x800050dc), 'T'},
+{PoreAddress(0x8000, 0x800021e8), 'T'},
+{PoreAddress(0x8000, 0x80000488), 'T'},
+{PoreAddress(0x800b, 0x80004700), 'T'},
+{PoreAddress(0x8000, 0x80000168), 'R'},
+{PoreAddress(0x8000, 0x80000138), 'R'},
+{PoreAddress(0x8000, 0x80000380), 'T'},
+{PoreAddress(0x800b, 0x800005cc), 'T'},
+{PoreAddress(0x800b, 0x800007dc), 'T'},
+{PoreAddress(0x8000, 0x8000272c), 'T'},
+{PoreAddress(0x800b, 0x800002b8), 'R'},
+{PoreAddress(0x8000, 0x80006208), 'T'},
+{PoreAddress(0x8000, 0x80000100), 'R'},
+{PoreAddress(0x800b, 0x80006ecc), 'T'},
+{PoreAddress(0x8000, 0x80000108), 'R'},
+{PoreAddress(0x8000, 0x8000718c), 'T'},
+{PoreAddress(0x800b, 0x80000290), 'R'},
+{PoreAddress(0x800b, 0x80004ca4), 'T'},
+{PoreAddress(0x800b, 0x80002048), 'T'},
+{PoreAddress(0x800b, 0x80002528), 'T'},
+{PoreAddress(0x800b, 0x800013bc), 'T'},
+{PoreAddress(0x800b, 0x80000148), 'R'},
+{PoreAddress(0x800b, 0x80002530), 'T'},
+{PoreAddress(0x800b, 0x80005ae4), 'T'},
+{PoreAddress(0x800b, 0x80002538), 'T'},
+{PoreAddress(0x8000, 0x80006ecc), 'T'},
+{PoreAddress(0x800b, 0x80002540), 'T'},
+{PoreAddress(0x8000, 0x800001d8), 'R'},
+{PoreAddress(0x8000, 0x80005690), 'T'},
+{PoreAddress(0x800b, 0x80002548), 'T'},
+{PoreAddress(0x8000, 0x80000328), 'R'},
+{PoreAddress(0x8000, 0x80000140), 'R'},
+{PoreAddress(0x8000, 0x800019d4), 'T'},
+{PoreAddress(0x8000, 0x80000808), 'T'},
+{PoreAddress(0x800b, 0x80000310), 'R'},
+{PoreAddress(0x8000, 0x80001d08), 'T'},
+{PoreAddress(0x800b, 0x800055a4), 'T'},
+{PoreAddress(0x800b, 0x800002a8), 'R'},
+{PoreAddress(0x8000, 0x800003ec), 'T'},
+{PoreAddress(0x8000, 0x80000148), 'R'},
+{PoreAddress(0x8000, 0x80006a94), 'T'},
+{PoreAddress(0x800b, 0x80004e0c), 'T'},
+{PoreAddress(0x8000, 0x8000100c), 'T'},
+{PoreAddress(0x800b, 0x80007090), 'T'},
+{PoreAddress(0x800b, 0x800005c4), 'T'},
+{PoreAddress(0x800b, 0x8000486c), 'T'},
+{PoreAddress(0x8000, 0x800003f0), 'T'},
+{PoreAddress(0x800b, 0x800006d0), 'T'},
+{PoreAddress(0x800b, 0x80005db4), 'T'},
+{PoreAddress(0x800b, 0x80007464), 'T'},
+{PoreAddress(0x800b, 0x80002558), 'T'},
+{PoreAddress(0x800b, 0x80000158), 'R'},
+{PoreAddress(0x800b, 0x800002e0), 'R'},
+{PoreAddress(0x800b, 0x800001a8), 'R'},
+{PoreAddress(0x8000, 0x80000318), 'R'},
+{PoreAddress(0x8000, 0x80005620), 'T'},
+{PoreAddress(0x800b, 0x800019d4), 'T'},
+{PoreAddress(0x8000, 0x800018d4), 'T'},
+{PoreAddress(0x8000, 0x80004704), 'T'},
+{PoreAddress(0x800b, 0x800051e8), 'T'},
+{PoreAddress(0x800b, 0x80001b68), 'T'},
+{PoreAddress(0x800b, 0x80000e34), 'T'},
+{PoreAddress(0x8000, 0x8000176c), 'T'},
+{PoreAddress(0x800b, 0x80007a2c), 'T'},
+{PoreAddress(0x8000, 0x80007a14), 'T'},
+{PoreAddress(0x800b, 0x800005c8), 'T'},
+{PoreAddress(0x8000, 0x8000099c), 'T'},
+{PoreAddress(0x800b, 0x80001968), 'T'},
+{PoreAddress(0x8000, 0x80007a18), 'T'},
+{PoreAddress(0x800b, 0x800003ec), 'T'},
+{PoreAddress(0x800b, 0x80000220), 'R'},
+{PoreAddress(0x800b, 0x800019ac), 'T'},
+{PoreAddress(0x8000, 0x80007a1c), 'T'},
+{PoreAddress(0x800b, 0x8000597c), 'T'},
+{PoreAddress(0x800b, 0x800060a0), 'T'},
+{PoreAddress(0x8000, 0x80007a20), 'T'},
+{PoreAddress(0x8000, 0x800004a8), 'T'},
+{PoreAddress(0x8000, 0x800002d8), 'R'},
+{PoreAddress(0x8000, 0x80007a24), 'T'},
+{PoreAddress(0x8000, 0x8000665c), 'T'},
+{PoreAddress(0x800b, 0x80000208), 'R'},
+{PoreAddress(0x8000, 0x8000702c), 'T'},
+{PoreAddress(0x800b, 0x80006bfc), 'T'},
+{PoreAddress(0x800b, 0x800049d4), 'T'},
+{PoreAddress(0x800b, 0x80000834), 'T'},
+{PoreAddress(0x8000, 0x80000280), 'R'},
+{PoreAddress(0x800b, 0x800001b0), 'R'},
+{PoreAddress(0x8000, 0x8000534c), 'T'},
+{PoreAddress(0x8000, 0x80000200), 'R'},
+{PoreAddress(0x8000, 0x80000e34), 'T'},
+{PoreAddress(0x8000, 0x800002a0), 'R'},
+{PoreAddress(0x800b, 0x80001314), 'T'},
+{PoreAddress(0x8000, 0x800060a0), 'T'},
+{PoreAddress(0x8000, 0x8000692c), 'T'},
+{PoreAddress(0x8000, 0x80000150), 'R'},
+{PoreAddress(0x800b, 0x80001970), 'T'},
+{PoreAddress(0x8000, 0x800002e8), 'R'},
+{PoreAddress(0x8000, 0x80007a28), 'T'},
+{PoreAddress(0x800b, 0x80001bd8), 'T'},
+{PoreAddress(0x800b, 0x8000190c), 'T'},
+{PoreAddress(0x800b, 0x80001d78), 'T'},
+{PoreAddress(0x800b, 0x80001f18), 'T'},
+{PoreAddress(0x8000, 0x80000414), 'T'},
+{PoreAddress(0x800b, 0x800020b8), 'T'},
+{PoreAddress(0x800b, 0x80002258), 'T'},
+{PoreAddress(0x8000, 0x80000218), 'R'},
+{PoreAddress(0x800b, 0x80000140), 'R'},
+{PoreAddress(0x8000, 0x8000048c), 'T'},
+{PoreAddress(0x8000, 0x80004700), 'T'},
+{PoreAddress(0x8000, 0x80005db4), 'T'},
+{PoreAddress(0x8000, 0x80002550), 'T'},
+{PoreAddress(0x800b, 0x80000298), 'R'},
+{PoreAddress(0x8000, 0x80007464), 'T'},
+{PoreAddress(0x8000, 0x800052cc), 'T'},
+{PoreAddress(0x800b, 0x80005814), 'T'},
+{PoreAddress(0x800b, 0x80006a94), 'T'},
+{PoreAddress(0x800b, 0x80005f38), 'T'},
+{PoreAddress(0x8000, 0x80000188), 'R'},
+{PoreAddress(0x800b, 0x800067c4), 'T'},
+{PoreAddress(0x8000, 0x80000f64), 'T'},
+{PoreAddress(0x8000, 0x800001c8), 'R'},
+{PoreAddress(0x8000, 0x80004ca4), 'T'},
+{PoreAddress(0x8000, 0x80006d64), 'T'},
+{PoreAddress(0x8000, 0x80001968), 'T'},
+{PoreAddress(0x800b, 0x80000318), 'R'},
+{PoreAddress(0x800b, 0x80000108), 'R'},
+{PoreAddress(0x800b, 0x80005620), 'T'},
+{PoreAddress(0x8000, 0x80002048), 'T'},
+{PoreAddress(0x8000, 0x800013bc), 'T'},
+{PoreAddress(0x800b, 0x800001c0), 'R'},
+{PoreAddress(0x8000, 0x8000597c), 'T'},
+{PoreAddress(0x800b, 0x800018d4), 'T'},
+{PoreAddress(0x800b, 0x800004a4), 'T'},
+{PoreAddress(0x800b, 0x800007b0), 'T'},
+{PoreAddress(0x8000, 0x80000208), 'R'},
+{PoreAddress(0x8000, 0x80000a84), 'T'},
+{PoreAddress(0x8000, 0x80007918), 'T'},
+{PoreAddress(0x800b, 0x8000773c), 'T'},
+{PoreAddress(0x8000, 0x80000178), 'R'},
+{PoreAddress(0x800b, 0x800019a8), 'T'},
+{PoreAddress(0x8000, 0x80000300), 'R'},
+{PoreAddress(0x800b, 0x800002d8), 'R'},
+{PoreAddress(0x800b, 0x80000198), 'R'},
+{PoreAddress(0x8000, 0x80000108), 'R'},
+{PoreAddress(0x800b, 0x800001e8), 'R'},
+{PoreAddress(0x8000, 0x80001938), 'T'},
+{PoreAddress(0x8000, 0x80000180), 'R'},
+{PoreAddress(0x8000, 0x80000320), 'R'},
+{PoreAddress(0x8000, 0x800016c4), 'T'},
+{PoreAddress(0x800b, 0x800014ec), 'T'},
+{PoreAddress(0x8000, 0x800001c0), 'R'},
+{PoreAddress(0x8000, 0x80004e0c), 'T'},
+{PoreAddress(0x800b, 0x8000534c), 'T'},
+{PoreAddress(0x8000, 0x80001970), 'T'},
+{PoreAddress(0x800b, 0x80001940), 'T'},
+{PoreAddress(0x800b, 0x800001c8), 'R'},
+{PoreAddress(0x800b, 0x800001a0), 'R'},
+{PoreAddress(0x8000, 0x800002b8), 'R'},
+{PoreAddress(0x800b, 0x80001ea8), 'T'},
+{PoreAddress(0x8000, 0x80000160), 'R'},
+{PoreAddress(0x8000, 0x800019a8), 'T'},
+{PoreAddress(0x8000, 0x800011e4), 'T'},
+{PoreAddress(0x800b, 0x8000100c), 'T'},
+{PoreAddress(0x800b, 0x8000692c), 'T'},
+{PoreAddress(0x800b, 0x8000189c), 'T'},
+{PoreAddress(0x800b, 0x80000150), 'R'},
+{PoreAddress(0x8000, 0x800064f4), 'T'},
+{PoreAddress(0x8000, 0x800014ec), 'T'},
+{PoreAddress(0x8000, 0x800001d0), 'R'},
+{PoreAddress(0x800b, 0x80007918), 'T'},
+{PoreAddress(0x8000, 0x800001b8), 'R'},
+{PoreAddress(0x800b, 0x800002f0), 'R'},
+{PoreAddress(0x8000, 0x80000288), 'R'},
+{PoreAddress(0x8000, 0x80000250), 'R'},
+{PoreAddress(0x8000, 0x800005d0), 'T'},
+{PoreAddress(0x800b, 0x80000178), 'R'},
+{PoreAddress(0x8000, 0x800051e8), 'T'},
+{PoreAddress(0x8000, 0x80001b68), 'T'},
+{PoreAddress(0x800b, 0x800002c0), 'R'},
+{PoreAddress(0x800b, 0x80000108), 'R'},
+{PoreAddress(0x8000, 0x800004a0), 'T'},
+{PoreAddress(0x8000, 0x800009dc), 'T'},
+{PoreAddress(0x800b, 0x80000278), 'R'},
+{PoreAddress(0x8000, 0x80000220), 'R'},
+{PoreAddress(0x8000, 0x80005f38), 'T'},
+{PoreAddress(0x800b, 0x8000095c), 'T'},
+{PoreAddress(0x8000, 0x80005ae4), 'T'},
+{PoreAddress(0x800b, 0x80002388), 'T'},
+{PoreAddress(0x800b, 0x800006d4), 'T'},
+{PoreAddress(0x8000, 0x80006bfc), 'T'},
+{PoreAddress(0x8000, 0x800049d4), 'T'},
+{PoreAddress(0x800b, 0x800072f8), 'T'},
+{PoreAddress(0x800b, 0x80000c5c), 'T'},
+{PoreAddress(0x800b, 0x8000176c), 'T'},
+{PoreAddress(0x800b, 0x800052cc), 'T'},
+{PoreAddress(0x800b, 0x800018a4), 'T'},
+{PoreAddress(0x800b, 0x80007a14), 'T'},
+{PoreAddress(0x8000, 0x80000190), 'R'},
+{PoreAddress(0x800b, 0x80007a18), 'T'},
+{PoreAddress(0x800b, 0x80006370), 'T'},
+{PoreAddress(0x800b, 0x80007a1c), 'T'},
+{PoreAddress(0x800b, 0x800071fc), 'T'},
+{PoreAddress(0x800b, 0x80007a20), 'T'},
+{PoreAddress(0x800b, 0x80007368), 'T'},
+{PoreAddress(0x800b, 0x80007a24), 'T'},
+{PoreAddress(0x800b, 0x800074d4), 'T'},
+{PoreAddress(0x8000, 0x800055a4), 'T'},
+{PoreAddress(0x800b, 0x800002f8), 'R'},
+{PoreAddress(0x8000, 0x80001314), 'T'},
+{PoreAddress(0x8000, 0x800002a8), 'R'},
+{PoreAddress(0x8000, 0x80000278), 'R'},
+{PoreAddress(0x800b, 0x80007640), 'T'},
+{PoreAddress(0x800b, 0x80005690), 'T'},
+{PoreAddress(0x8000, 0x80000860), 'T'},
+{PoreAddress(0x800b, 0x800077ac), 'T'},
+{PoreAddress(0x8000, 0x800050dc), 'T'},
+{PoreAddress(0x800b, 0x80000328), 'R'},
+{PoreAddress(0x8000, 0x80002388), 'T'},
+{PoreAddress(0x800b, 0x800002c8), 'R'},
+{PoreAddress(0x800b, 0x80000280), 'R'},
+{PoreAddress(0x8000, 0x8000113c), 'T'},
+{PoreAddress(0x800b, 0x80000200), 'R'},
+{PoreAddress(0x800b, 0x80000228), 'R'},
+{PoreAddress(0x800b, 0x800002a0), 'R'},
+{PoreAddress(0x8000, 0x80001bd8), 'T'},
+{PoreAddress(0x8000, 0x80000158), 'R'},
+{PoreAddress(0x8000, 0x8000773c), 'T'},
+{PoreAddress(0x8000, 0x80001d78), 'T'},
+{PoreAddress(0x8000, 0x80001f18), 'T'},
+{PoreAddress(0x8000, 0x800020b8), 'T'},
+{PoreAddress(0x8000, 0x80002258), 'T'},
+{PoreAddress(0x800b, 0x800023f8), 'T'},
+{PoreAddress(0x800b, 0x800003f0), 'T'},
+{PoreAddress(0x8000, 0x800001f8), 'R'},
+{PoreAddress(0x800b, 0x80000300), 'R'},
+{PoreAddress(0x800b, 0x80000120), 'R'},
+{PoreAddress(0x8000, 0x800018cc), 'T'},
+{PoreAddress(0x800b, 0x80000320), 'R'},
+{PoreAddress(0x8000, 0x80005814), 'T'},
+{PoreAddress(0x8000, 0x8000189c), 'T'},
+{PoreAddress(0x800b, 0x8000048c), 'T'},
+{PoreAddress(0x8000, 0x800001e0), 'R'},
+{PoreAddress(0x8000, 0x800067c4), 'T'},
+{PoreAddress(0x8000, 0x800023f8), 'T'},
+{PoreAddress(0x800b, 0x800001f0), 'R'},
+{PoreAddress(0x8000, 0x800002d0), 'R'},
+{PoreAddress(0x8000, 0x800002f0), 'R'},
+{PoreAddress(0x800b, 0x80000160), 'R'},
+{PoreAddress(0x8000, 0x80000308), 'R'},
+{PoreAddress(0x800b, 0x800004a8), 'T'},
+{PoreAddress(0x8000, 0x80004f74), 'T'},
+{PoreAddress(0x8000, 0x800002c0), 'R'},
+{PoreAddress(0x800b, 0x80000188), 'R'},
+{PoreAddress(0x8000, 0x80004b3c), 'T'},
+{PoreAddress(0x800b, 0x800001d0), 'R'},
+{PoreAddress(0x8000, 0x80007090), 'T'},
+{PoreAddress(0x8000, 0x800007b0), 'T'},
+{PoreAddress(0x800b, 0x80000bb4), 'T'},
+{PoreAddress(0x800b, 0x800005d0), 'T'},
+{PoreAddress(0x800b, 0x80000f64), 'T'},
+{PoreAddress(0x8000, 0x800072f8), 'T'},
+{PoreAddress(0x8000, 0x800051d4), 'T'},
+{PoreAddress(0x8000, 0x800005cc), 'T'},
+{PoreAddress(0x800b, 0x80006d64), 'T'},
+{PoreAddress(0x8000, 0x800018a4), 'T'},
+{PoreAddress(0x800b, 0x80001910), 'T'},
+{PoreAddress(0x8000, 0x800002e0), 'R'},
+{PoreAddress(0x8000, 0x80006370), 'T'},
+{PoreAddress(0x8000, 0x800071fc), 'T'},
+{PoreAddress(0x800b, 0x800021e8), 'T'},
+{PoreAddress(0x8000, 0x80007368), 'T'},
+{PoreAddress(0x8000, 0x800074d4), 'T'},
+{PoreAddress(0x800b, 0x800001e0), 'R'},
+{PoreAddress(0x8000, 0x800001e8), 'R'},
+{PoreAddress(0x8000, 0x800002f8), 'R'},
+{PoreAddress(0x800b, 0x800002e8), 'R'},
+{PoreAddress(0x8000, 0x80007640), 'T'},
+{PoreAddress(0x800b, 0x80000a84), 'T'},
+{PoreAddress(0x8000, 0x800077ac), 'T'},
+{PoreAddress(0x800b, 0x80000138), 'R'},
+{PoreAddress(0x8000, 0x800002c8), 'R'},
+};
+
+static void
+init()
+{
+int i;
+FAPI_INF("HookManager : "
+ "Indexing global symbols for bin/sbe_pnor.out");
+for (i = 0; i < 374; i++) {
+ HookManager::registerGlobalSymbol(symbols[i], &(info[i]));
+}
+}
+
+static HookInitializer initializer(init);
diff --git a/src/usr/pore/poreve/makefile b/src/usr/pore/poreve/makefile
new file mode 100644
index 000000000..b1a2b0b89
--- /dev/null
+++ b/src/usr/pore/poreve/makefile
@@ -0,0 +1,67 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/pore/pore_model/makefile $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2011
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or other-
+# wise divested of its trade secrets, irrespective of what has
+# been deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END
+
+# Module poreve built from 3 different source code areas:
+#
+# model The source code of the PoreInterface and PoreModel classes,
+# including the Transaction model. This pair of abstract classes
+# is implemented on the model side by a hardware model
+# (e.g., pore_model), and on the interface side by a virtual
+# environment (e.g., poreve).
+#
+# pore_model Model the hardware of the PORE. This containts the "pore-engine-core/interpreter" of the PORe simulation
+# The code in this directory is owned by Boeblingen team.
+#
+# porevesrc The Source code of the PoreVe class, including the Bus and
+# Slave models, and the HookManager.
+#
+ROOTPATH = ../../../..
+MODULE = poreve
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/ecmddatabuffer
+EXTRAINCDIR += ${ROOTPATH}/src/usr/pore/poreve/model
+EXTRAINCDIR += ${ROOTPATH}/src/usr/pore/poreve/pore_model/include
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/fapi
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/plat
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/hwp
+EXTRAINCDIR += ${ROOTPATH}/src/usr/pore/poreve/porevesrc
+
+CUSTOMFLAGS += -D__BYTE_ORDER=1 -D__BIG_ENDIAN=1 -D__LITTLE_ENDIAN=0 -DFASTI2C_BASE_OFFSET=0 -DDEBUG_FASTI2C=1 -D_BIG_ENDIAN=1
+
+# Override to use C++ compiler for %.c/h files
+CC_OVERRIDE = 1
+
+OBJS = poreveutil.o
+OBJS += transaction.o poreaddress.o poremodel.o poreregister.o poreinterface.o porestate.o
+OBJS += pore_model.o pore_bus.o pore_fi2c.o pore_inline_decode.o vsbe.o
+OBJS += pore.o bus.o hookmanager.o poreve.o pib2cfam.o fasti2c.o sbevital.o create.o
+HOOK_SOURCE_FILES = $(notdir $(wildcard ./hook/*sbe*.hooks.cc))
+OBJS += $(patsubst %.cc,%.o,$(HOOK_SOURCE_FILES))
+
+vpath %.C ./model/
+vpath %.C ./pore_model/wrapper/
+# Note: small c files
+vpath %.c ./pore_model/ibuf/
+vpath %.C ./porevesrc/
+vpath %.cc ./hook/
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/pore/poreve/model/bebits.H b/src/usr/pore/poreve/model/bebits.H
new file mode 100644
index 000000000..403dbe53a
--- /dev/null
+++ b/src/usr/pore/poreve/model/bebits.H
@@ -0,0 +1,48 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/model/bebits.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_BEBITS_H
+#define __VSBE_BEBITS_H
+
+// $Id: bebits.H,v 1.3 2011/06/30 03:34:58 bcbrock Exp $
+
+/// \file bebits.H
+/// \brief Bit manipulation for Big-Endian data
+
+
+/// A bit mask for a range of bits in a big-endian uint64_t
+#define BE64_MASK(begin, end) \
+ ((0xffffffffffffffffull >> (64 - ((end) - (begin) + 1))) << (63 - (end)))
+
+/// A single bit mask for a big-endian uint64_t
+#define BE64_BIT(n) (BE64_MASK((n), (n)))
+
+/// Extract an unsigned field from a uint64_t
+#define BE64_GET_FIELD(x, begin, end) \
+ (((x) & BE64_MASK((begin), (end))) >> (63 - (end)))
+
+/// Update an unsigned field in a uint64_t from a right-justified uint64_t value
+#define BE64_SET_FIELD(x, begin, end, val) \
+ ((((val) << (63 - (end))) & BE64_MASK((begin), (end))) | \
+ ((x) & ~BE64_MASK((begin), (end))))
+
+#endif // __VSBE_BEBITS_H
diff --git a/src/usr/pore/poreve/model/modelerror.H b/src/usr/pore/poreve/model/modelerror.H
new file mode 100644
index 000000000..41d42687e
--- /dev/null
+++ b/src/usr/pore/poreve/model/modelerror.H
@@ -0,0 +1,149 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/model/modelerror.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_MODELERROR_H
+#define __VSBE_MODELERROR_H
+
+// $Id: modelerror.H,v 1.9 2011/07/07 03:51:52 bcbrock Exp $
+
+/// \file modelerror.H
+/// \brief An enumeration of modeling errors
+
+namespace vsbe {
+
+ /// \enum ModelError
+ ///
+ /// A large number of error conditions can arise in the PORE VE model,
+ /// ranging all the way from bugs in the model to bugs in the virtual
+ /// firmware. The PORE VE model includes an enumeration of all of these
+ /// errors for error reporting and to aid in finding bugs. We chose to use
+ /// this mechanism rather than defining a FAPI error for each error case
+ /// since a FAPI error code may imply a complex error diagnosis and/or
+ /// recovery path, while it's likely that most ModelError that halt
+ /// simulation are firmware bugs that will be handled the same way.
+
+ enum ModelError {
+
+ /// No error. This code is permanently assigned to 0, so code is free
+ /// to either check for 0 or for ME_SUCCESS.
+ ME_SUCCESS = 0,
+ /// A generic failure from an operation in the environment
+ ME_FAILURE = 1,
+ /// An improperly configured model that is missing a bus connection
+ ME_NO_BUS_MODEL = 2,
+ /// A HOOK instruction hook returned an error
+ ME_HOOK_INSTRUCTION_ERROR = 3,
+ /// A read hook returned an error
+ ME_HOOK_READ_ERROR = 4,
+ /// A write hook returned an error
+ ME_HOOK_WRITE_ERROR = 5,
+ /// A fetch hook returned an error
+ ME_HOOK_FETCH_ERROR = 6,
+ /// The PORE model was constructed but never initialized
+ ME_PORE_UNINITIALIZED = 7,
+ /// A generic error from the underlying PoreModel
+ ME_PORE_MODEL_GENERIC_ERROR = 8,
+ /// A transaction size error
+ ME_SIZE_ERROR = 9,
+ /// An error ocurred on the registerRead() method
+ ME_REGISTER_READ_ERROR = 10,
+ /// An error ocurred on the registerWrite() method
+ ME_REGISTER_WRITE_ERROR = 11,
+ /// Transaction address is not in any known memory map
+ ME_NOT_MAPPED_ON_BUS = 12,
+ /// Transaction address is in a memory map but not in the memory image
+ ME_NOT_MAPPED_IN_MEMORY = 13,
+ /// Transaction mode denied by slave permissions found with transaction address
+ ME_BUS_SLAVE_PERMISSION_DENIED = 14,
+ /// Transaction mode denied by MemoryImage permissions
+ ME_MEMORY_IMAGE_PERMISSION_DENIED = 15,
+ /// There is a bug in the model
+ ME_BUG = 16,
+ /// The WAIT implementation failed for some reason
+ ME_WAIT_FAILURE = 17,
+ /// There was an error reading or writing a register in the PoreState
+ ME_PORE_STATE_ERROR = 18,
+ /// Attempting to read a write-only register
+ ME_WRITE_ONLY_REGISTER = 19,
+ /// Attempting to write a read-only register
+ ME_READ_ONLY_REGISTER = 20,
+ /// Request for an illegal or unmodeled register
+ ME_ILLEGAL_REGISTER_OFFSET = 21,
+ /// An illegal mode or setting was programmed in the I2C controller
+ ME_FASTI2C_CONTROL_ERROR = 22,
+ /// An illegal register sequence was attempted on the I2C controller
+ ME_FASTI2C_SEQUENCE_ERROR = 23,
+ /// A configuration is duplicate or ambiguous
+ ME_DUPLICATE_CONFIGURATION = 24,
+ /// A requested device is not mapped on the I2C controller
+ ME_NOT_MAPPED_ON_FASTI2C_CONTROLLER = 25,
+ /// An illegal address was presented to or computed by an I2C memory
+ ME_I2CMEMORY_ILLEGAL_ADDRESS = 26,
+ /// Invalid argument
+ ME_INVALID_ARGUMENT = 27,
+ /// LPC (PNOR) access outside of ECC bounds
+ ME_LPC_ILLEGAL_ADDRESS = 28,
+ /// An illegal usage of PoreModel::forceBranch()
+ ME_ILLEGAL_FORCED_BRANCH = 29,
+ };
+};
+
+/// HBI doesn't want strings - however for lab/test applications it's nice to
+/// be able to print the error codes. This macro can be instantiated to
+/// provide this facility.
+
+#define MODEL_ERROR_STRINGS(var) \
+ const char* const var[] = { \
+ "Success", \
+ "A generic failure from an operation in the environment", \
+ "An improperly configured model that is missing a bus connection", \
+ "A HOOK instruction hook returned an error", \
+ "A read hook returned an error", \
+ "A write hook returned an error", \
+ "A fetch hook returned an error", \
+ "The PORE model was constructed but never initialized", \
+ "A generic error from the underlying PoreModel", \
+ "A transaction size error", \
+ "An error ocurred on the registerRead() method", \
+ "An error ocurred on the registerWrite() method", \
+ "Transaction address is not in any known memory map", \
+ "Transaction address is in a memory map but not in the memory image", \
+ "Transaction mode denied by slave permissions found with transaction address", \
+ "Transaction mode denied by MemoryImage permissions", \
+ "There is a bug in the model", \
+ "The WAIT implementation failed for some reason", \
+ "There was an error reading or writing a register in the PoreState", \
+ "Attempting to read a write-only register", \
+ "Attempting to write a read-only register", \
+ "Request for an illegal or unmodeled register", \
+ "An illegal mode or setting was programmed for I2C", \
+ "An illegal register sequence was attempted on the I2C controller", \
+ "A configuration is duplicate or ambiguous", \
+ "A requested device is not mapped on the I2C controller", \
+ "An illegal address was presented to or computed by an I2C memory", \
+ "Invalid argument", \
+ "LPC (PNOR) access outside of ECC bounds,", \
+ "An illegal usage of PoreModel::forceBranch()", \
+ };
+
+#endif // __VSBE_MODELERROR_H
+
diff --git a/src/usr/pore/poreve/model/poreaddress.C b/src/usr/pore/poreve/model/poreaddress.C
new file mode 100644
index 000000000..84bcaeeee
--- /dev/null
+++ b/src/usr/pore/poreve/model/poreaddress.C
@@ -0,0 +1,78 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/model/poreaddress.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// $Id: poreaddress.C,v 1.1 2011/06/08 13:12:50 bcbrock Exp $
+
+/// \file poreaddress.C
+/// \brief A simple abstract PORE address that separates the memory space from
+/// the offset.
+
+#include "poreaddress.H"
+
+using namespace vsbe;
+
+////////////////////////////////////////////////////////////////////////////
+// PoreAddress
+////////////////////////////////////////////////////////////////////////////
+
+PoreAddress::PoreAddress()
+{
+
+}
+
+
+PoreAddress::PoreAddress(uint16_t i_memorySpace, uint32_t i_offset) :
+ iv_offset(i_offset),
+ iv_memorySpace(i_memorySpace)
+{
+}
+
+
+PoreAddress::PoreAddress(uint64_t i_address) :
+ iv_offset(i_address & 0xffffffff),
+ iv_memorySpace((i_address >> 32) & 0xffff)
+{
+}
+
+
+PoreAddress::~PoreAddress()
+{
+}
+
+
+PoreAddress::operator uint64_t () const
+{
+ return ((uint64_t)iv_memorySpace << 32) | iv_offset;
+}
+
+
+PoreAddress&
+PoreAddress::setFromPibAddress(uint32_t i_pibAddress)
+{
+ uint64_t address = i_pibAddress;
+
+ iv_memorySpace = (address >> 16) & 0xffff;
+ iv_offset = (address & 0xffff) << 3;
+
+ return *this;
+}
+
diff --git a/src/usr/pore/poreve/model/poreaddress.H b/src/usr/pore/poreve/model/poreaddress.H
new file mode 100644
index 000000000..ef2578ac1
--- /dev/null
+++ b/src/usr/pore/poreve/model/poreaddress.H
@@ -0,0 +1,117 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/model/poreaddress.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_POREADDRESS_H
+#define __VSBE_POREADDRESS_H
+
+// $Id: poreaddress.H,v 1.2 2012/01/06 21:25:15 bcbrock Exp $
+
+/// \file poreaddress.H
+/// \brief A simple abstract PORE address that separates the memory space from
+/// the offset.
+
+#include <stdint.h>
+
+namespace vsbe {
+
+ class PoreAddress;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreAddress
+////////////////////////////////////////////////////////////////////////////
+
+/// A PORE address
+///
+/// PORE implements a segmented memory architecure. An address consists of a
+/// 16-bit memory space identifier and a 32-bit byte offset within the memory
+/// space. The memory space identifer denotes the physical memory interface
+/// used for the memory (PIB or OCI). For PIB addresses, the memory space
+/// also encodes direct vs. indirect memory access protocols.
+///
+/// Inside the PORE the memory space Id is held in the 16 high-order bits of
+/// the program counter. Relative branches and relative subroutine branches
+/// do not modify the memory space. All other branches, including immediate
+/// branches, indirect (dereferenced) branches and return from subroutine
+/// update the entire 48-bit PC, and hence change the default memory space.
+///
+/// The address registers also include an incomplete memory space field; the
+/// field is incomplete because it does not include the PIB/Memory bit which
+/// is implied. These memory space Ids are set by loading the registers. The
+/// address register memory spaces are only valid for the SBE engine; for all
+/// of the OCI-attached PORE engines the address registers only allow OCI
+/// access and ignore the memory space Id.
+///
+/// Since this is a simple type (equivalent to a uint64_t) we allow the
+/// compiler to create the copy and assignment operators for the class.
+
+class
+vsbe::PoreAddress {
+
+public:
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ /// Construct an uninitialized PoreAddress
+ PoreAddress ();
+
+ /// Construct a PoreAddress from a memory space Id + offset
+ ///
+ /// \param[in] i_memorySpace The 16-bit memory space descriptor
+ ///
+ /// \param[in] i_offset The 32-bit byte address within the memory space
+ PoreAddress(uint16_t i_memorySpace, uint32_t i_offset);
+
+ /// Construct a PoreAddress from a right-justified uint64_t
+ ///
+ /// \param[in] i_address;
+ PoreAddress(uint64_t i_address);
+
+ ~PoreAddress();
+
+ //////////////////////////// Operators ////////////////////////////
+
+ /// Convert a PoreAddress to a uint64_t
+ operator uint64_t () const;
+
+ //////////////////////////// Manipulators ////////////////////////////
+
+ /// Convert a PIB address into a PoreAddress
+ ///
+ /// \param[in] i_pibAddress Assumed to be the PIB address of a location in
+ /// a direct access PIB memory, the address is converted to the equivalent
+ /// PORE address form
+ ///
+ /// \retval address A reference to the object
+ PoreAddress& setFromPibAddress(uint32_t i_pibAddress);
+
+ ////////////////////////// Implementation ////////////////////////////
+
+ /// The byte offset within the memory space
+ uint32_t iv_offset;
+
+ /// The memory space identifier
+ uint16_t iv_memorySpace;
+};
+
+#endif // __VSBE_POREADDRESS_H
diff --git a/src/usr/pore/poreve/model/poreconstants.H b/src/usr/pore/poreve/model/poreconstants.H
new file mode 100644
index 000000000..b2d946711
--- /dev/null
+++ b/src/usr/pore/poreve/model/poreconstants.H
@@ -0,0 +1,275 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/model/poreconstants.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_PORECONSTANTS_H
+#define __VSBE_PORECONSTANTS_H
+
+// $Id: poreconstants.H,v 1.3 2011/10/14 21:35:19 bcbrock Exp $
+
+/// \file poreconstants.H
+/// \brief Constants associated with the The PORE hardware interface classes
+
+#include <stdint.h>
+
+namespace vsbe {
+
+ /// PORE instruction buffer IDs
+ ///
+ /// These are the PORE instruction buffer IDs that PORE programs can read
+ /// out as the low-order 4 bits of the IDFLAGS register. This allows a
+ /// PORE program to determine which engine it is running on. Most
+ /// importantly, the Ibuf ID is required by various constructors and
+ /// methods as there are hardware differences between the various engines.
+ enum PoreIbufId {
+ PORE_GPE0 = 0,
+ PORE_GPE1 = 1,
+ PORE_SLW = 8,
+ PORE_SBE = 4
+ };
+
+ /// \defgroup pore_status PORE Hardware Abstract Status
+ ///
+ /// The PoreModel produces an abstract status return code that succinctly
+ /// captures the state of the machine. The status consists of an
+ /// OR-combination of the PORE_STATUS_* flags. The status flags
+ /// effectively enumerate all of the reasons that the PORE engine may be
+ /// physically or abstractly halted or unrunnable. A status of 0
+ /// indicates that the PORE engine is runnable and ready to execute the
+ /// next instruction. Since several of these conditions could be true at
+ /// once, the status is represented as an OR-mask rather than as a C++
+ /// enum.
+ ///
+ /// Most of the status conditions require a specific action to clear the
+ /// status and allow instruction execution to resume. Some conditions are
+ /// considered fatal and require a reset() to continue.
+ ///
+ /// \note The status is currently compiled only by examining the PORE
+ /// state that is visible in the hardware. Currently this makes it
+ /// difficult to determine unequivically why the engine stopped. Change
+ /// requests are pending for the hardware to correct this. If it remains
+ /// difficult to determine from hardware status precisely why the PORE
+ /// engine is stopped, then we will have to decide whether to include APIs
+ /// in the virtual environment to transmit this information, and perhaps
+ /// diverge the capabilities of the virtual PORE from the real PORE.
+
+ /// @{
+
+ /// The PORE executed a WAIT 0 (HALT) instruction
+ ///
+ /// This condition is determined by noting that the PORE is stopped, and
+ /// the instruction currently visible in the IBUF0 register is WAIT 0. To
+ /// continue, the user should either restart() the machine or write a
+ /// value into the EXE_TRIGGER register. Simply continuing from a HALT
+ /// would resume execution at the instruction following the HALT, and the
+ /// PoreModel::run() method will not continue execution as long as
+ /// this condition is true.
+ const int PORE_STATUS_HALTED = 0x01;
+
+ /// The PORE halted due to an architected error
+ ///
+ /// This bit is determined by seeing the PORE is stopped and examining bit
+ /// 63 of PIBMS_DBG. 'Debug registers are locked'. To continue, the user
+ /// should restart () the machine. The PoreModel::run() method will not
+ /// continue execution as long as this condition is true.
+ const int PORE_STATUS_ERROR_HALT = 0x02;
+
+ /// The PORE is in the hardware STOP state
+ ///
+ /// This flag indicates that bit 0 of the PORE control register is set,
+ /// signifying that the hardware is stopped. The stop may be due to a
+ /// halt, error halt, trap or address breakpoint, or may have been
+ /// commanded by the user. The PoreModel::run() method will normally
+ /// continue execution from this condition unless specifically prohibited
+ /// by another status bit.
+ const int PORE_STATUS_HARDWARE_STOP = 0x04;
+
+ /// The PORE stopped due to an address breakpoint
+ ///
+ /// This condition is determined by noting that the PORE engine is stopped
+ /// in the ABR state, and either 1) the current PC is equal to the visible
+ /// address breakpoint address, or 2) the PORE_STATUS_TRAP condition is
+ /// not met. The second condition would arise if the address breakpoint
+ /// hit on a taken branch, because in the case the PC will end up pointing
+ /// to the branch target. If this status is set, the PoreModel::run()
+ /// method will generate the correct sequence to continue execution.
+ const int PORE_STATUS_BREAKPOINT = 0x08;
+
+ /// The PORE hit an enabled trap
+ ///
+ /// This condition is determined by noting that the PORE engine is stopped
+ /// in the ABR state, the TRAP instruction is enabled, and the instruction
+ /// currently visible in the IBUF0 register is a TRAP. If this status is
+ /// set, the PoreModel::run() method will generate the correct sequence to
+ /// continue execution.
+ const int PORE_STATUS_TRAP = 0x10;
+
+ /// The PORE model experienced a modeling error
+ ///
+ /// This conditon only exists in the virtual PORE model, and indicates
+ /// that the \a iv_ModelError attribute of the PoreModel is non-0. The
+ /// only ways to continue from this error are to restart() the machine or
+ /// to call the clearModelError() method, as the PoreModel::run() method
+ /// will not continue execution as long as this condition is true.
+ const int PORE_STATUS_MODEL_ERROR = 0x20;
+
+ /// A debug stop
+ ///
+ /// This flag indicates that application code requested a stop by using
+ /// the stop() method, and the getStopCode() method can be used to recover
+ /// the argument of the stop() call. This is a debugging aid for use by
+ /// hooks, and does not actually stop the hardware. The PoreModel::run()
+ /// method will normally continue execution from this condition unless
+ /// specifically prohibited by another status bit.
+ const int PORE_STATUS_DEBUG_STOP = 0x40;
+
+ /// @};
+
+
+ /// \enum PoreRegisterOffset
+ ///
+ /// These are the 8-byte aligned address offsets for 4- and 8-byte
+ /// register accesses. For 4-byte accesses to the low-order word of an
+ /// 8-byte register, add 4 to the offset.
+ ///
+ /// These are the OCI address-space offsets used for the PORE-SLW,
+ /// PORE-GPE0 and PORE-GPE1 models. The PORE-SBE has a PIB interface, and
+ /// in that case the PIB slave (SCOM) offsets are actually these offsets /
+ /// 8. For consistency across all models we use the OCI offset below for
+ /// all PORE instances however, including the PORE-SBE.
+ ///
+ /// The PORE engine contains a number of visible registers, however there
+ /// remains state that is not visible but must be saved/restored to
+ /// checkpoint the engine. The final entry in the enumeration defines the
+ /// total size (in bytes) of the PORE state. This constant is used in the
+ /// definition of the PoreState struct. The area between
+ /// SIZEOF_VISIBLE_PORE_STATE and SIZEOF_PORE_STATE is model-specific,
+ /// programmer-invisible data. Currently there is no established protocol
+ /// for moving states between different software models or between
+ /// software and hardware models due to the presence of non-architected
+ /// state. The hidden state variables are enumerated for consistency with
+ /// the fapiPoreVe text-based register save/restore methodology.
+ ///
+ /// The register names appearing below are taken from the PORE hardware
+ /// specification.
+ enum PoreRegisterOffset {
+ // Visible registers
+ PORE_STATUS = 0x00,
+ PORE_CONTROL = 0x08,
+ PORE_RESET = 0x10,
+ PORE_ERROR_MASK = 0x18,
+ PORE_PRV_BASE_ADDR0 = 0x20,
+ PORE_PRV_BASE_ADDR1 = 0x28,
+ PORE_OCI_MEMORY_BASE_ADDR0 = 0x30,
+ PORE_OCI_MEMORY_BASE_ADDR1 = 0x38,
+ PORE_TABLE_BASE_ADDR = 0x40,
+ PORE_EXE_TRIGGER = 0x48,
+ PORE_EXE_TRIGGER_HI = 0x4c, // Programmer-writable bits 32:63
+ PORE_SCRATCH0 = 0x50,
+ PORE_SCRATCH1 = 0x58,
+ PORE_SCRATCH2 = 0x60,
+ PORE_IBUF_01 = 0x68,
+ PORE_IBUF_2 = 0x70,
+ PORE_DBG0 = 0x78,
+ PORE_DBG1 = 0x80,
+ PORE_PC_STACK0 = 0x88,
+ PORE_PC_STACK1 = 0x90,
+ PORE_PC_STACK2 = 0x98,
+ PORE_ID_FLAGS = 0xa0,
+ PORE_DATA0 = 0xa8,
+ PORE_MEM_RELOC = 0xb0,
+ PORE_I2C_E0_PARAM = 0xb8,
+ PORE_I2C_E1_PARAM = 0xc0,
+ PORE_I2C_E2_PARAM = 0xc8,
+ // The size of the visible state
+ SIZEOF_VISIBLE_PORE_STATE = 0xd0,
+ // Add hidden state variables
+ PORE_HIDDEN_STATE_0 = 0xd0,
+ PORE_HIDDEN_STATE_1 = 0xd8,
+ PORE_HIDDEN_STATE_2 = 0xe0,
+ PORE_HIDDEN_STATE_3 = 0xe8,
+ PORE_HIDDEN_STATE_4 = 0xf0,
+ SIZEOF_PORE_STATE = 0xf8,
+ // An illegal offset, for robust error checking
+ PORE_ILLEGAL = 0xff
+ };
+
+ /// \enum PoreRegisterEncoding
+ ///
+ /// These are the 4-bit encodings used in the PORE instruction set to
+ /// identify the programmaer-visible registers. These are the register
+ /// names and encodings as defined in the PGAS manual. Abstract register
+ /// names are defined as extra encodings. Every register named here must
+ /// also be mapped in PORE_REGISTER_MAP.
+ enum PoreRegisterEncoding {
+ // These are "real" register encodings
+ PORE_P0 = 0x0,
+ PORE_P1 = 0x1,
+ PORE_A0 = 0x2,
+ PORE_A1 = 0x3,
+ PORE_CTR = 0x4,
+ PORE_D0 = 0x5,
+ PORE_D1 = 0x6,
+ PORE_EMR = 0x7,
+ PORE_ETR = 0x9,
+ PORE_SPRG0 = 0xa,
+ PORE_PC = 0xe,
+ PORE_IFR = 0xf,
+ // These are model-only encodings
+ PORE_CIA = 0x10
+ };
+
+ /// This constant maps a PoreRegisterEncoding to the PoreRegisterOffset of
+ /// the register that contains the programmer-visible or abstract register.
+ const PoreRegisterOffset PORE_REGISTER_MAP[] = {
+ // These are "real" register encodings
+ PORE_PRV_BASE_ADDR0, // 0x0
+ PORE_PRV_BASE_ADDR1, // 0x1
+ PORE_OCI_MEMORY_BASE_ADDR0, // 0x2
+ PORE_OCI_MEMORY_BASE_ADDR1, // 0x3
+ PORE_SCRATCH0, // 0x4
+ PORE_SCRATCH1, // 0x5
+ PORE_SCRATCH2, // 0x6
+ PORE_ERROR_MASK, // 0x7
+ PORE_ILLEGAL, // 0x8
+ PORE_EXE_TRIGGER, // 0x9
+ PORE_DATA0, // 0xa
+ PORE_ILLEGAL, // 0xb
+ PORE_ILLEGAL, // 0xc
+ PORE_ILLEGAL, // 0xd
+ PORE_STATUS, // 0xe
+ PORE_ID_FLAGS, // 0xf
+ // These are model-only encodings
+ PORE_DBG1 // 0x10
+ };
+
+ /// 'Infinity' for the purposes of the Pore run() method.
+ const uint64_t RUN_UNLIMITED = 0xffffffffffffffffull;
+
+ /// The 'Stop Code' used by setPc() when it stops the processor.
+ const int STOP_CODE_SET_PC = -1;
+
+ /// A bogus address to install as the breakpoint address to effectively
+ /// disable PORE address breakpoints.
+ const uint64_t PORE_UNBREAKABLE_ADDRESS = 0xfffffffffffcull;
+};
+
+#endif // __VSBE_PORECONSTANTS_H
diff --git a/src/usr/pore/poreve/model/poreinterface.C b/src/usr/pore/poreve/model/poreinterface.C
new file mode 100644
index 000000000..6adef3b60
--- /dev/null
+++ b/src/usr/pore/poreve/model/poreinterface.C
@@ -0,0 +1,242 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/model/poreinterface.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// $Id: poreinterface.C,v 1.7 2011/10/12 19:55:53 bcbrock Exp $
+
+/// \file poreinterface.C
+/// \brief The PORE hardware interface class
+
+#include "poreinterface.H"
+#include "poremodel.H"
+
+using namespace vsbe;
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreInterface
+////////////////////////////////////////////////////////////////////////////
+
+
+int
+PoreInterface::restart()
+{
+ return iv_model->restart();
+}
+
+
+int
+PoreInterface::run(const uint64_t i_instructions, uint64_t& o_ran)
+{
+ return iv_model->run(i_instructions, o_ran);
+}
+
+
+ModelError
+PoreInterface::stop(const int i_stopCode)
+{
+ return iv_model->stop(i_stopCode);
+}
+
+
+ModelError
+PoreInterface::modelError(const ModelError i_modelError)
+{
+ return iv_model->modelError(i_modelError);
+}
+
+
+void
+PoreInterface::clearModelError()
+{
+ return iv_model->clearModelError();
+}
+
+
+ModelError
+PoreInterface::clearHardwareErrors()
+{
+ return iv_model->clearHardwareErrors();
+}
+
+
+ModelError
+PoreInterface::registerRead(const PoreRegisterOffset i_offset,
+ uint64_t& o_data,
+ const size_t i_size)
+{
+ return iv_model->registerRead(i_offset, o_data, i_size);
+}
+
+
+ModelError
+PoreInterface::registerWrite(const PoreRegisterOffset i_offset,
+ const uint64_t i_data,
+ const size_t i_size)
+{
+ return iv_model->registerWrite(i_offset, i_data, i_size);
+}
+
+
+ModelError
+PoreInterface::registerReadRaw(const PoreRegisterOffset i_offset,
+ uint64_t& o_data,
+ const size_t i_size)
+{
+ return iv_model->registerReadRaw(i_offset, o_data, i_size);
+}
+
+
+ModelError
+PoreInterface::registerWriteRaw(const PoreRegisterOffset i_offset,
+ const uint64_t i_data,
+ const size_t i_size)
+{
+ return iv_model->registerWriteRaw(i_offset, i_data, i_size);
+}
+
+
+void
+PoreInterface::enableHookInstruction(bool i_enable)
+{
+ iv_model->enableHookInstruction(i_enable);
+}
+
+
+void
+PoreInterface::enableAddressHooks(bool i_enable)
+{
+ iv_model->enableAddressHooks(i_enable);
+}
+
+
+ModelError
+PoreInterface::extractState(PoreState& o_state)
+{
+ return iv_model->extractState(o_state);
+}
+
+
+ModelError
+PoreInterface::installState(const PoreState& i_state)
+{
+ return iv_model->installState(i_state);
+}
+
+ModelError
+PoreInterface::forceBranch(const PoreAddress& i_address)
+{
+ return iv_model->forceBranch(i_address);
+}
+
+
+ModelError
+PoreInterface::setPc(const PoreAddress& i_address)
+{
+ return iv_model->setPc(i_address);
+}
+
+
+ModelError
+PoreInterface::setBreakpoint(const PoreAddress& i_address)
+{
+ return iv_model->setBreakpoint(i_address);
+}
+
+
+ModelError
+PoreInterface::disableBreakpoint()
+{
+ return setBreakpoint(PORE_UNBREAKABLE_ADDRESS);
+}
+
+
+ModelError
+PoreInterface::enableTrap(const bool i_enable)
+{
+ return iv_model->enableTrap(i_enable);
+}
+
+
+int
+PoreInterface::getStatus()
+{
+ return iv_model->getStatus();
+}
+
+
+ModelError
+PoreInterface::getModelError()
+{
+ return iv_model->getModelError();
+}
+
+
+uint64_t
+PoreInterface::getInstructions()
+{
+ return iv_model->getInstructions();
+}
+
+
+int
+PoreInterface::getStopCode()
+{
+ return iv_model->getStopCode();
+}
+
+
+PoreInterface::PoreInterface(PoreIbufId i_id) :
+ d0(this, PORE_D0),
+ d1(this, PORE_D1),
+ a0(this, PORE_A0),
+ a1(this, PORE_A1),
+ p0(this, PORE_P0),
+ p1(this, PORE_P1),
+ ctr(this, PORE_CTR),
+ emr(this, PORE_EMR),
+ etr(this, PORE_ETR),
+ sprg0(this, PORE_SPRG0),
+ pc(this, PORE_PC),
+ ifr(this, PORE_IFR),
+ cia(this, PORE_CIA),
+ iv_model(0)
+{
+ newModel(i_id);
+}
+
+
+PoreInterface::~PoreInterface()
+{
+ delete iv_model;
+}
+
+
+void
+PoreInterface::newModel(PoreIbufId i_id)
+{
+ delete iv_model;
+ iv_model = PoreModel::create(i_id, this);
+ iv_ibufId = i_id;
+}
+
+
+
diff --git a/src/usr/pore/poreve/model/poreinterface.H b/src/usr/pore/poreve/model/poreinterface.H
new file mode 100644
index 000000000..9c8b44974
--- /dev/null
+++ b/src/usr/pore/poreve/model/poreinterface.H
@@ -0,0 +1,346 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/model/poreinterface.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_POREINTERFACE_H
+#define __VSBE_POREINTERFACE_H
+
+// $Id: poreinterface.H,v 1.10 2011/11/07 23:39:33 bcbrock Exp $
+
+/// \file poreinterface.H
+/// \brief The PORE hardware interface class
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "bebits.H"
+#include "modelerror.H"
+#include "poreaddress.H"
+#include "transaction.H"
+#include "poreconstants.H"
+#include "poreregister.H"
+#include "porestate.H"
+
+// This is required for debugging prints only
+#if 1
+#include <stdio.h>
+#endif
+
+namespace vsbe {
+
+ class PoreAddress;
+ class PoreInterface;
+ class PoreModel;
+ class PoreState;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreInterface
+////////////////////////////////////////////////////////////////////////////
+
+
+/// Abstract base class for the PORE hardware engine virtual environment
+///
+/// PoreInterface is an abstract class that specifies the interfaces that a
+/// virtual environment must implement on behalf of the abstract PoreModel,
+/// and provides the control interfaces into the PoreModel. Applications will
+/// never operate on the PoreModel directly, but instead will operate
+/// exclusively on classes derived from PoreInterface.
+
+class
+vsbe::PoreInterface {
+
+public:
+
+ ///////////////////////// Control Interface /////////////////////////
+
+ /// See PoreModel::restart()
+ virtual int
+ restart();
+
+ /// See PoreModel::run()
+ virtual int
+ run(const uint64_t i_instructions, uint64_t& o_ran);
+
+ /// See PoreModel::stop()
+ virtual ModelError
+ stop(const int i_stopCode);
+
+ /// See PoreModel::modelError()
+ virtual ModelError
+ modelError(const ModelError i_modelError);
+
+ /// See PoreModel::clearModelError()
+ virtual void
+ clearModelError();
+
+ /// See PoreModel::clearHardwareErrors()
+ virtual ModelError
+ clearHardwareErrors();
+
+ /// See PoreModel::registerRead()
+ virtual ModelError
+ registerRead(const PoreRegisterOffset i_offset,
+ uint64_t& o_data,
+ const size_t i_size = 8);
+
+ /// See PoreModel::registerWrite()
+ virtual ModelError
+ registerWrite(const PoreRegisterOffset i_offset,
+ const uint64_t i_data,
+ const size_t i_size = 8);
+
+ /// See PoreModel::registerReadRaw()
+ virtual ModelError
+ registerReadRaw(const PoreRegisterOffset i_offset,
+ uint64_t& o_data,
+ const size_t i_size = 8);
+
+ /// See PoreModel::registerWriteRaw()
+ virtual ModelError
+ registerWriteRaw(const PoreRegisterOffset i_offset,
+ const uint64_t i_data,
+ const size_t i_size = 8);
+
+ /// See PoreModel::enableHookInstruction()
+ virtual void
+ enableHookInstruction(bool i_enable);
+
+ /// See PoreModel::enableAddressHooks()
+ virtual void
+ enableAddressHooks(bool i_enable);
+
+ /// See PoreModel::extractState()
+ virtual ModelError
+ extractState(PoreState& o_state);
+
+ /// See PoreModel::installState()
+ virtual ModelError
+ installState(const PoreState& i_state);
+
+ /// See PoreModel::forceBranch()
+ virtual ModelError
+ forceBranch(const PoreAddress& i_address);
+
+ /// See PoreModel::setPc()
+ virtual ModelError
+ setPc(const PoreAddress& I_pc);
+
+ /// See PoreModel::setBreakpoint()
+ virtual ModelError
+ setBreakpoint(const PoreAddress& i_address);
+
+ /// Effectively disable the PORE address breakpoint
+ ///
+ /// \retval 0 Success
+ ///
+ /// \retval non-0 Any ModelError returned by underlying hardware
+ /// operations.
+ virtual ModelError
+ disableBreakpoint();
+
+ /// See PoreModel::enableTrap()
+ virtual ModelError
+ enableTrap(const bool i_enable);
+
+ /// See PoreModel::getStatus()
+ virtual int
+ getStatus();
+
+ /// See PoreModel::getModelError()
+ virtual ModelError
+ getModelError();
+
+ /// See PoreModel::getInstructions()
+ virtual uint64_t
+ getInstructions();
+
+ /// See PoreModel::getStopCode()
+ virtual int
+ getStopCode();
+
+
+ //////////////////// Abstract Interface /////////////////////////
+
+ /// See PoreModel::pibMaster()
+ virtual void
+ pibMaster(PibTransaction& io_transaction) = 0;
+
+ /// See PoreModel::ociMaster()
+ virtual void
+ ociMaster(OciTransaction& io_transaction) = 0;
+
+ /// See PoreModel::wait()
+ virtual void
+ wait(const uint32_t i_count) = 0;
+
+ /// See PoreModel::hookInstruction()
+ virtual void
+ hookInstruction(const PoreAddress& i_address,
+ const uint32_t i_hook,
+ const uint64_t i_parameter) = 0;
+
+ /// See PoreModel::hookRead()
+ virtual void
+ hookRead(const PoreAddress& i_address) = 0;
+
+ /// See PoreModel::hookWrite()
+ virtual void
+ hookWrite(const PoreAddress& i_address) = 0;
+
+ /// See PoreModel::hookFetch()
+ virtual void
+ hookFetch(const PoreAddress& i_address) = 0;
+
+ /// See PoreModel::errorIntr()
+ virtual void
+ errorIntr(void) = 0;
+
+ /// See PoreModel::fatalErrorIntr()
+ virtual void
+ fatalErrorIntr(void) = 0;
+
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ /// Create the PoreInterface
+ ///
+ /// \param[in] i_id The IBUF ID (PORE engine type) of the PORE model to
+ /// create.
+ PoreInterface(PoreIbufId i_id);
+
+ virtual ~PoreInterface();
+
+
+ ///////////////////// Register Interface ////////////////////////////
+
+ /// \defgroup pore_register_access PORE Register Access
+ ///
+ /// These data members of PoreInterface provide easy access to
+ /// programmer-visible and abstract registers for use by procedures and
+ /// hooks. Unless otherwise indicated in the brief comment the register is
+ /// both readable and writable. Data registers, address registers, the
+ /// counter register and some control register values are right justfied,
+ /// and only the indicated number of bits are writable. Other hardware
+ /// control registers have unique layouts. See the detailed comments for
+ /// each register and the comments for the PoreRegister class for more
+ /// information.
+ ///
+ /// @{
+
+ /// 64-bit data register D0
+ PoreDataBuffer d0;
+ /// 64-bit data register D1
+ PoreDataBuffer d1;
+ /// 32-bit address register A0
+ PoreRegisterWritable a0;
+ /// 32-bit address register A1
+ PoreRegisterWritable a1;
+ /// 7-bit pervasive chiplet register P0
+ PoreRegisterWritable p0;
+ /// 7-bit pervasive chiplet register P1
+ PoreRegisterWritable p1;
+ /// 24-bit counter CTR
+ PoreRegisterWritable ctr;
+ /// 21-bit error mask register
+ ///
+ /// The EMR is implemented as a 64-bit registers, however only the
+ /// high-order 21 bits contain information.
+ PoreRegisterWritable emr;
+ /// 64-bit EXE-Trigger Register - Partially writable
+ ///
+ /// The low-order 32 bits of the EXE-Trigger register are writable from a
+ /// PORE program. The register is fully writable externally, however this
+ /// has the major side effect of kicking off a new PORE program if the
+ /// high-order 32-bits are written. The write implementation here only
+ /// writes the low-order 32 bits; to write the entire register call
+ /// registerWrite() directly.
+ PoreRegisterWritable etr;
+ /// 32-bit Special-Purpose General Register 0
+ PoreRegisterWritable sprg0;
+ /// PC - Read-only
+ ///
+ /// The 48-bit PC is read-only using the PoreRegister interface. Setting
+ /// the PC requires using the setPc() procedure on the PoreInterface.
+ /// It's likely that a hook programmer should actually be using the
+ /// abstract \c CIA register.
+ PoreRegister pc;
+ /// ID-Flags Register - Partial read-only
+ ///
+ /// Note that from inside a PORE program this register is read-only.
+ /// Externally the ALU flags fields of the register are writable, so this
+ /// behavior is supported. The writable portion (the flags) are bits
+ /// 48:55.
+ PoreRegisterWritable ifr;
+ /// Current instruction address - Read-Only
+ ///
+ /// This is an abstract register. If the PORE engine is running or stopped
+ /// at a breakpoint or trap then reading the CIA returns the address of
+ /// the currently executing instruction. If the PORE engine is stopped in
+ /// a wait state then reading the CIA returns the address of the last
+ /// instruction executed.
+ ///
+ /// This register is read-only. If the intention is to force a branch
+ /// then the forceBranch() or setPc() methods of the PoreInterface should
+ /// be used.
+ PoreRegister cia;
+
+ /// @}
+
+ ////////////////////////// Implementation ////////////////////////////
+
+protected:
+
+ /// Create a new underlying model
+ ///
+ /// \param[in] i_id The IBUF ID (PORE engine type) of the PORE model to
+ /// create.
+ ///
+ /// This method creates and installs an instance of the PoreModel with a
+ /// specific PoreIbufId. This method is provided separately from the
+ /// constructor to support use of the PoreInterface in the Simics
+ /// environment. In Simics, the type of the engine (GPE0, SLW, etc.) is
+ /// not known until after model construction, but before actual simulation
+ /// begins. In Simics models are created with a default type, then later
+ /// recreated using newModel() once the actual type is known.
+ virtual void
+ newModel(PoreIbufId i_id);
+
+ /// The IBUF ID (engine type) of the PORE being modeled
+ PoreIbufId iv_ibufId;
+
+private:
+
+ /// The associated PoreModel
+ ///
+ /// This object is created and destroyed by the PoreInterface.
+ PoreModel* iv_model;
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ PoreInterface(const PoreInterface& rhs);
+ PoreInterface& operator=(const PoreInterface& rhs);
+};
+
+
+#endif // __VSBE_POREINTERFACE_H
diff --git a/src/usr/pore/poreve/model/poremodel.C b/src/usr/pore/poreve/model/poremodel.C
new file mode 100644
index 000000000..dfa8cbbbc
--- /dev/null
+++ b/src/usr/pore/poreve/model/poremodel.C
@@ -0,0 +1,439 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/model/poremodel.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// $Id: poremodel.C,v 1.19 2011/11/11 00:50:35 bcbrock Exp $
+
+/// \file poremodel.C
+/// \brief The PORE hardware engine model and interface to the virtual
+/// environment.
+
+#include "poremodel.H"
+
+using namespace vsbe;
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreModel
+////////////////////////////////////////////////////////////////////////////
+
+/////////////// Common Creation/Control Interface ////////////////////
+
+int
+PoreModel::restart()
+{
+ flushReset();
+ iv_modelError = ME_SUCCESS;
+ iv_instructions = 0;
+ iv_stopCode = 0;
+ return getStatus();
+}
+
+
+// run() refuses to do anything if the status shows a model error or an error
+// halt. Otherwise the status is used to determine how to restart the machine
+// if it is currently stopped. Then the model is stepped until the number of
+// instructions has been executed or the status is non-0. If a debug stop was
+// requested this condition is recorded so that PORE_STATUS_DEBUG_STOP can be
+// added back to the status at the end.
+
+// Note: The system model or hooks may call modelError() to update the private
+// iv_modelError field to record errors that are not otherwise visible to the
+// PORE hardware model. This will cause the PORE_STATUS_MODEL_ERROR to be set
+// and terminate the run loop. However note that the instruction will
+// complete on the PORE.
+
+// Note: run(0, ran) simply has the effect of making a stopped machine
+// runnable.
+
+// Note: This method will need to be overridden/reimplemented in a derived
+// class that controls actual PORE hardware or a simulation model.
+
+int
+PoreModel::run(const uint64_t i_instructions, uint64_t& o_ran)
+{
+ uint64_t n = i_instructions;
+ uint64_t control;
+ ModelError me = ME_SUCCESS;
+ bool stepped;
+ bool writeControl = false;
+ int iv_status;
+
+ do {
+
+ o_ran = 0;
+ iv_stopCode = 0;
+ iv_status = getStatus();
+
+ if (iv_status & (PORE_STATUS_ERROR_HALT | PORE_STATUS_MODEL_ERROR)) {
+ break;
+ }
+
+ me = registerRead(PORE_CONTROL, control);
+ if (me != 0) break;
+
+ if (iv_status & PORE_STATUS_HARDWARE_STOP) {
+ control &= ~BE64_BIT(0);
+ writeControl = true;
+ }
+ if (iv_status & (PORE_STATUS_BREAKPOINT | PORE_STATUS_TRAP)) {
+ control |= BE64_BIT(1);
+ writeControl = true;
+ }
+
+ if (writeControl) {
+ me = registerWrite(PORE_CONTROL, control);
+ }
+ if (me != 0) break;
+
+ while (n--) {
+ me = step(stepped);
+ if ((me != 0) || !stepped) {
+ break;
+ }
+ o_ran++;
+ iv_instructions++;
+ if (getModelError() != 0) {
+ break;
+ }
+ }
+
+ } while (0);
+
+ if (me != 0) {
+ modelError(me);
+ }
+
+ return getStatus();
+}
+
+
+ModelError
+PoreModel::stop(const int i_stopCode)
+{
+ uint64_t control;
+ ModelError me;
+
+ do {
+ me = iv_modelError;
+ if (me) break;
+ me = registerRead(PORE_CONTROL, control);
+ if (me) break;
+ me = registerWrite(PORE_CONTROL, control | BE64_BIT(0));
+ if (me) break;
+ if (i_stopCode != 0) {
+ iv_stopCode = i_stopCode;
+ }
+ } while (0);
+
+ return me;
+}
+
+ModelError
+PoreModel::modelError(const ModelError i_modelError)
+{
+ if (i_modelError != 0) {
+ iv_modelError = i_modelError;
+ }
+ return i_modelError;
+}
+
+
+void
+PoreModel::clearModelError()
+{
+ iv_modelError = ME_SUCCESS;
+}
+
+
+ModelError
+PoreModel::clearHardwareErrors()
+{
+ ModelError me;
+
+ me = registerWrite(PORE_DBG0, 0);
+ if (me == 0) {
+ me = registerWrite(PORE_DBG1, 0);
+ }
+ return me;
+}
+
+
+// Set the PC as specified, leaving the engine in the stopped state. By
+// hardware specification, if the control register is written with the set_pc
+// bit set, then the only action is to update the PC, which comes in as the
+// low-order 48 bits of the CONTROL register.
+
+ModelError
+PoreModel::setPc(const PoreAddress& i_pc)
+{
+ do {
+
+ if (iv_modelError != 0) break;
+ stop(STOP_CODE_SET_PC);
+ if (iv_modelError != 0) break;
+
+ iv_modelError =
+ registerWrite(PORE_CONTROL, (uint64_t)i_pc | BE64_BIT(3));
+
+ } while (0);
+ return iv_modelError;
+}
+
+
+// The breakpoint address occupies the lower 48 bits of the control register.
+
+ModelError
+PoreModel::setBreakpoint(const PoreAddress& i_address)
+{
+ uint64_t control, address;
+ ModelError me;
+
+ do {
+
+ me = registerRead(PORE_CONTROL, control);
+ if (me != 0) break;
+
+ address = i_address;
+ control &= ~BE64_MASK(16, 63);
+ control |= address;
+
+ me = registerWrite(PORE_CONTROL, control);
+ if (me != 0) break;
+
+ } while (0);
+ return me;
+}
+
+
+// Bit 11 of the PORE CONTROL register is the TRAP enable bit.
+
+ModelError
+PoreModel::enableTrap(const bool i_enable)
+{
+ ModelError me;
+ uint64_t control;
+
+ me = registerRead(PORE_CONTROL, control);
+ if (me == 0) {
+ if (i_enable) {
+ control |= BE64_BIT(11);
+ } else {
+ control &= ~BE64_BIT(11);
+ }
+ me = registerWrite(PORE_CONTROL, control);
+ }
+ return me;
+}
+
+
+// Abstract status bits are set as documented. If a ModelError is present the
+// state is assumed to be corrupted so PORE_STATUS_MODEL_ERROR is the only
+// status returned.
+
+int
+PoreModel::getStatus()
+{
+
+ ModelError me;
+ uint64_t control, status, ibuf01, dbg1;
+ int finalStatus;
+ const unsigned PORE_OPCODE_WAIT = 1;
+ const unsigned PORE_OPCODE_TRAP = 2;
+ const unsigned PORE_STATE_ABR = 0xb; // PORE HW State machine state
+
+ do {
+
+ finalStatus = 0;
+ me = iv_modelError;
+ if (me != 0) break;
+
+ me = registerRead(PORE_CONTROL, control);
+ if (me != 0) break;
+ me = registerRead(PORE_STATUS, status);
+ if (me != 0) break;
+ me = registerRead(PORE_IBUF_01, ibuf01);
+ if (me != 0) break;
+ me = registerRead(PORE_DBG1, dbg1);
+ if (me != 0) break;
+
+ // Status associated with the hardware stop condition
+
+ if (control & BE64_BIT(0)) {
+
+ finalStatus |= PORE_STATUS_HARDWARE_STOP;
+
+ if ((BE64_GET_FIELD(ibuf01, 0, 6) == PORE_OPCODE_WAIT) &&
+ (BE64_GET_FIELD(ibuf01, 8, 31) == 0)) {
+ finalStatus |= PORE_STATUS_HALTED;
+ }
+
+ if (dbg1 & BE64_BIT(63)) {
+ finalStatus |= PORE_STATUS_ERROR_HALT;
+ }
+ }
+
+ // Status associated with the engine being in the ABR (Address
+ // BReakpoint) state. We need to disambiguate TRAP, BREAKPOINT, and
+ // TRAP+BREAKPOINT. This is needlesssly complicated due to lack of
+ // direct hardware status.
+
+ if (BE64_GET_FIELD(status, 3, 6) == PORE_STATE_ABR) {
+
+ if ((BE64_GET_FIELD(ibuf01, 0, 6) == PORE_OPCODE_TRAP) &&
+ BE64_GET_FIELD(control, 11, 11)) {
+ finalStatus |= PORE_STATUS_TRAP;
+ }
+
+ if (BE64_GET_FIELD(control, 16, 63) ==
+ BE64_GET_FIELD(status, 16, 63)) {
+ finalStatus |= PORE_STATUS_BREAKPOINT;
+ } else {
+ if (!(finalStatus & PORE_STATUS_TRAP)) {
+ finalStatus |= PORE_STATUS_BREAKPOINT;
+ }
+ }
+ }
+ } while (0);
+
+ if (iv_stopCode != 0) {
+ finalStatus |= PORE_STATUS_DEBUG_STOP;
+ }
+
+ if (me != 0) {
+ modelError(me);
+ finalStatus = PORE_STATUS_MODEL_ERROR;
+ }
+
+ return finalStatus;
+}
+
+
+ModelError
+PoreModel::getModelError()
+{
+ return iv_modelError;
+}
+
+
+uint64_t
+PoreModel::getInstructions()
+{
+ return iv_instructions;
+}
+
+
+int
+PoreModel::getStopCode()
+{
+ return iv_stopCode;
+}
+
+
+//////////////////// PoreInterface Methods /////////////////////////
+
+// The interface methods are responsible for ensuring that any errors are
+// captured in the iv_modelError member of the PoreModel.
+
+void
+PoreModel::pibMaster(PibTransaction& transaction)
+{
+ iv_interface->pibMaster(transaction);
+}
+
+
+void
+PoreModel::ociMaster(OciTransaction& transaction)
+{
+ iv_interface->ociMaster(transaction);
+}
+
+
+void
+PoreModel::wait(const uint32_t i_count)
+{
+ iv_interface->wait(i_count);
+}
+
+
+void
+PoreModel::hookInstruction(const PoreAddress& i_address,
+ const uint32_t i_hook,
+ const uint64_t i_parameter)
+{
+ iv_interface->hookInstruction(i_address, i_hook, i_parameter);
+}
+
+
+void
+PoreModel::hookRead(const PoreAddress& i_address)
+{
+ iv_interface->hookRead(i_address);
+}
+
+
+void
+PoreModel::hookWrite(const PoreAddress& i_address)
+{
+ iv_interface->hookWrite(i_address);
+}
+
+
+void
+PoreModel::hookFetch(const PoreAddress& i_address)
+{
+ iv_interface->hookFetch(i_address);
+}
+
+
+void
+PoreModel::errorIntr(void)
+{
+ iv_interface->errorIntr();
+}
+
+
+void
+PoreModel::fatalErrorIntr(void)
+{
+ iv_interface->fatalErrorIntr();
+}
+
+
+////////////////////////////// Creators //////////////////////////////
+
+PoreModel::PoreModel(PoreIbufId i_id, PoreInterface *i_interface) :
+ iv_ibufId(i_id),
+ iv_modelError(ME_PORE_UNINITIALIZED),
+ iv_instructions(0),
+ iv_stopCode(0),
+ iv_interface(i_interface)
+{
+}
+
+
+PoreModel::~PoreModel()
+{
+}
+
+
+
+
diff --git a/src/usr/pore/poreve/model/poremodel.H b/src/usr/pore/poreve/model/poremodel.H
new file mode 100644
index 000000000..be2446c1f
--- /dev/null
+++ b/src/usr/pore/poreve/model/poremodel.H
@@ -0,0 +1,733 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/model/poremodel.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_POREMODEL_H
+#define __VSBE_POREMODEL_H
+
+// $Id: poremodel.H,v 1.23 2011/11/11 00:55:26 bcbrock Exp $
+
+/// \file poremodel.H
+/// \brief The PORE hardware engine model
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modelerror.H"
+#include "poreinterface.H"
+#include "transaction.H"
+
+// This is required for debugging prints only
+#if 1
+#include <stdio.h>
+#endif
+
+namespace vsbe {
+
+ class PoreAddress;
+ class PoreInterface;
+ class PoreModel;
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreModel
+////////////////////////////////////////////////////////////////////////////
+
+
+/// Abstract base class for the PORE hardware engine model
+///
+/// PoreModel is an abstract class that specifies the interfaces that a PORE
+/// model will use to communicate to the virtual environment, and that the
+/// environment will use to control the model. This class is designed to
+/// allow different implementations of PoreModel to be easily interchanged;
+/// see the create() method.
+///
+/// The PoreModel is completely abstracted from the environment, however. The
+/// PoreModel communicates with the environment through a subclass of the
+/// PoreInterface class. This PoreInterface arranges for the implementation
+/// of the externalized PoreModel operations.
+
+class
+vsbe::PoreModel {
+
+public:
+
+ /////////////// Common Creation/Control Interface ////////////////////
+
+ /// Create a new instance of a model derived from PoreModel
+ ///
+ /// \param[in] i_id The IBUF ID (PORE engine type) of the model to
+ /// create.
+ ///
+ /// \param[in] i_interface A pointer back to the PoreInterface that
+ /// creates and owns this object and implements several of the PoreModel
+ /// methods. This parameter must be provided to the base class
+ /// constructor.
+ ///
+ /// To facilitate swapping different PORE hardware models in and out
+ /// transparently, this abstract base class declares a static function
+ /// that creates an instance of the model to use. Whoever provides the
+ /// implementation of the derived class must define this method to produce
+ /// an instance of the derived class the conforms to a PORE hardware
+ /// engine of the parameterized type.
+ static PoreModel*
+ create(PoreIbufId i_id, PoreInterface *i_interface);
+
+ /// Restart the PORE engine to its scan-flush state
+ ///
+ /// For PORE-SBE, the engine is reset to begin execution from the OTPROM
+ /// at the proper location, with all configuration registers (e.g., the
+ /// I2C configuration) flushed to the correct state to begin an IPL.
+ ///
+ /// For the other engines, they are reset as documented and will not run
+ /// (correctly) until the BASE address and EXE trigger registers are
+ /// written. As a side effect the status of the PoreModel is computed and
+ /// returned. The PoreModel is defined to be in the restart (scan-flush)
+ /// state at the end of constructing the model.
+ ///
+ /// \retval status PORE-SBE returns 0 (running); The other engines return
+ /// PORE_STATUS_HARDWARE_STOP.
+ ///
+ /// \bug Check to make sure this is true for the SBE.
+ virtual int
+ restart();
+
+ /// Step the model by (at most) N instructions
+ ///
+ /// \param[in] i_instructions The (maximum) number of instructions to
+ /// execute. Use the constant RUN_UNLIMITED to run (effectively) forever.
+ ///
+ /// \param[out] o_ran The number of instructions that actually ran. This
+ /// may be 0 if \a i_instructions is 0, or if the PoreModel was in an
+ /// unrunnable state when run() was invoked. To find the total number of
+ /// instructions that have run since model construction (or the last
+ /// restart()), use the method getInstructions().
+ ///
+ /// When this method is invoked it is assumed that the caller wants the
+ /// model to run, regardless of its current state. The run() method first
+ /// attempts to make a stopped machine runnable, and then attempts to
+ /// execute \a i_instructions and returns the final status and the number
+ /// of instructions actually completed by this invocation.
+ ///
+ /// - If the engine shows an error status before the execution of run()
+ /// then no instructions will be executed and \a o_ran will be returned as
+ /// 0. To clear the error status use clearModelError() or
+ /// clearHardwareErrors() to continue with restart()-ing the machine.
+ ///
+ /// - If the engine shows a stopped or error status at any time after the
+ /// execution of the first instruction but before the execution of the
+ /// final requested instruction, then run() returns at that point and \a
+ /// o_ran indicates how many instructions were actually executed.
+ ///
+ /// - Calling run() with \a i_instructions == 0 simply makes a stopped
+ /// machine runnable (if possible).
+ ///
+ /// Note that executing a single instruction may entail many bus
+ /// transactions, especially in the case of the SCAND command which is
+ /// treated as single instructions. WAIT is also considered a single
+ /// instruction regardless of the wait count.
+ ///
+ /// \retval 0 The PORE remains runnable. In this case \a o_ran == \a
+ /// i_instructions.
+ ///
+ /// \retval status An OR-combination of 1 or more PORE_STATUS_* flags
+ /// indicating the final state of the PORE.
+ virtual int
+ run(const uint64_t i_instructions, uint64_t& o_ran);
+
+ /// Signal a debug-stop
+ ///
+ /// \param[in] i_stopCode A user-defined integer code to categorize the
+ /// reason for the stop. Use \a i_stopCode == 0 to simply stop the
+ /// machine. Use a non-zero stop code to also cause
+ /// PORE_STATUS_DEBUG_STOP to be set in the final status.
+ ///
+ /// This API is provided for control programs or debugging code
+ /// (e.g. hooks) to force the simulation to stop during the execution of
+ /// the run() method, or to insure that the PORE engine is stopped and in
+ /// the WAIT state prior to updating or examining the state. The effect of
+ /// stop() is to terminate any ongoing run() method immediately by writing
+ /// the PORE \c stop_start bit with a 1. Calling the stop() method with a
+ /// non-zero \a i_stopCode leaves the PORE abstract status with the
+ /// PORE_STATUS_DEBUG_STOP bit set, and the \a i_stopCode provided can be
+ /// later recovered with the getStopCode() method. Calling stop() multiple
+ /// times with non-zero \a i_stopCode only records the last
+ /// instance. Absent any error conditions a subsequent call of run() will
+ /// restart the simulation.
+ ///
+ /// \retval me Returns 0 for success, otherwise any ModelError
+ /// encountered during processing of the method. If the engine has
+ /// ModelError status prior to the call the method returns that status
+ /// immediately (does not perform the stop() operation).
+ virtual ModelError
+ stop(const int i_stopCode);
+
+ /// Signal a modeling error
+ ///
+ /// \param[in] i_modelError A model-defined integer code to categorize the
+ /// type of modeling error. If the model status includes
+ /// PORE_STATUS_MODEL_ERROR then the getModelError() method returns this
+ /// code, otherwise 0. If \a i_modelError is 0 then this method has no
+ /// effect. If modelError() is called multiple times with non-0 \a
+ /// i_modelError during the execution of a single instruction then only
+ /// the last non-0 value is recorded.
+ ///
+ /// This API is provided as a way for the system-level model or
+ /// application debugging code (e.g. hooks) to force the simulation to
+ /// halt with an error during the execution of the run() method. The
+ /// effect of the modelError() with a non-0 \a i_modelError parameter is
+ /// to terminate a run() immediately and leave the PORE abstract status
+ /// with the PORE_STATUS_MODEL_ERROR bit set. This is a fatal error; The
+ /// model will not run instructions again until restart()-ed or the error
+ /// is explicitly cleared with clearModelError().
+ ///
+ /// \retval i_modelError This routine returns its input \a i_modelError.
+ virtual ModelError
+ modelError(const ModelError i_modelError);
+
+ /// Clear any ModelError from the model
+ ///
+ /// Note that the run() method will stop immediately and not continue a
+ /// model that has a non-0 ModelError status. This method allows the user
+ /// to clear the ModelError status and continue execution.
+ virtual void
+ clearModelError();
+
+ /// Clear PORE hardware error status
+ ///
+ /// PORE hardware error status is stored in the PORE DBG0 and DBG1
+ /// registers. This procedure clears both of those registers to allow a
+ /// simulation (or run) to continue in the event of a hardware error.
+ /// Note that is a second hardware error occurs while the debug registers
+ /// are "locked" (i.e., holding an error) the PORE hardware engine will
+ /// halt.
+ ///
+ /// \retval me Will be non-0 if an error occurs during the procedure.
+ virtual ModelError
+ clearHardwareErrors();
+
+ /// Set the program counter
+ ///
+ /// \param i_pc The new program counter
+ ///
+ /// This method encapsulates the hardware register operations required to
+ /// force-set the PORE program counter. This method first calls stop() to
+ /// halt the PORE engine. If the engine is at a trap or breakpoint the
+ /// stop() will take the engine back to the WAIT state, otherwise the new
+ /// PC can not be guaranteed to take effect. The PC is then updated. The
+ /// engine is \e not restarted (if it had been running); At the end of
+ /// this method the hardware will always be in the stopped state.
+ ///
+ /// \retval me Returns 0 for success, otherwise any ModelError
+ /// encountered during processing of the method. If the engine has
+ /// ModelError status prior to the call the method returns that status
+ /// immediately (does not perform the setPc() operation).
+ virtual ModelError
+ setPc(const PoreAddress& i_pc);
+
+ /// Set the PORE address breakpoint
+ ///
+ /// \param[in] i_address The breakpoint address
+ ///
+ /// The PORE supports a single address breakpoint, and calling this API
+ /// sets the breakpoint. If the PC ever matches the breakpoint address
+ /// then the PORE engine stops after executing an instruction at that
+ /// address.
+ ///
+ /// The PORE address breakpoint can not be explicitly disabled, however
+ /// the constant vsbe::PORE_UNBREAKABLE_ADDRESS contains a phony address
+ /// that can be installed as the breakpoint address to effectively disable
+ /// the address breakpopint.
+ ///
+ /// \retval me Returns 0 for success, otherwise any ModelError
+ /// encountered during processing of the method.
+ virtual ModelError
+ setBreakpoint(const PoreAddress& i_address);
+
+ /// Enable or disable the TRAP instruction
+ ///
+ /// \param[in] i_enable Controls whether TRAP is enabled or disabled.
+ ///
+ /// By default (or when TRAP is disabled) the TRAP instruction is treated
+ /// by the PORE hardware as a NOP. If enabled the TRAP instruction causes
+ /// PORE execution to break in the Address-Breakpoint state, similar to an
+ /// address breakpoint. The run() method automatically restarts execution
+ /// if the PORE engine is stopped in this state.
+ ///
+ /// \retval me Will be returned non-0 if any errors are encountered
+ /// executing the procedure.
+ virtual ModelError
+ enableTrap(const bool i_enable);
+
+ /// Return the current abstract status
+ ///
+ /// \retval status The current PoreModel abstract status as an
+ /// OR-combination of PORE_STATUS_* bits. See \ref pore_status.
+ virtual int
+ getStatus();
+
+ /// Return the current PoreModel error code
+ ///
+ /// \retval error If the PORE status includes the bit
+ /// PORE_STATUS_MODEL_ERROR then getModelError() returns the ModelError
+ /// responsible, otherwise 0.
+ virtual ModelError
+ getModelError();
+
+ /// Return the number of executed instructions
+ ///
+ /// \retval instrctions The total number of instructions executed since
+ /// the model was created or restart()-ed.
+ virtual uint64_t
+ getInstructions();
+
+ /// Return the code supplied with the last stop() method.
+ ///
+ /// \retval code If the PORE status includes the bit
+ /// PORE_STATUS_DEBUG_STOP, then getStopCode() returns the parameter
+ /// supplied with the last stop() call that caused the PORE model to stop.
+ virtual int
+ getStopCode();
+
+
+ ///////////////////////// Abstract Interface /////////////////////////
+
+ /// Reset the PORE engine to its scan-flush state
+ ///
+ /// For PORE-SBE, the engine is reset to execute the first instruction of
+ /// OTPROM. For the other engines, they are reset as documented and will
+ /// not run (correctly) until the BASE address and EXE trigger registers
+ /// are written. The PoreModel is defined to be in the reset
+ /// (scan-flush) state at the end of constructing the model.
+ ///
+ /// \retval me Return values other than 0 indicate some type of error in
+ /// the reset as defined by the ModelError enumeration.
+ virtual ModelError
+ flushReset() = 0;
+
+ /// Step the PORE engine one instruction
+ ///
+ /// \param[out] o_stepped This parameter is set to true or false depending
+ /// on whether the model successfully completed a step.
+ ///
+ /// Step the model 1 instruction, unless the model is presently in an
+ /// unrecoverable error state, or the step itself causes an unrecoverable
+ /// error.
+ ///
+ /// Executing a single instruction may entail many bus transactions,
+ /// especially in the case of the SCAND command which is treated as a
+ /// single instruction. WAIT is also considered a single instruction
+ /// regardless of the wait count. Finally, the PORE hardware may also be
+ /// in a state where it can not execute an instruction without an external
+ /// control action.
+ ///
+ /// \retval me Return values other than 0 indicate some type of error in
+ /// the step as defined by the ModelError enumeration.
+ virtual ModelError
+ step(bool& o_stepped) = 0;
+
+ /// Read a user-visible control or data register \e with side effects
+ ///
+ /// \param[in] i_offset The register offset (see below).
+ ///
+ /// \param[out] o_data The returned data. For 4-byte reads the data is
+ /// right justified.
+ ///
+ /// \param[in] i_size The size in bytes (see below).
+ ///
+ /// In general the PORE supports both 4- and 8-byte access to the control
+ /// and data register space. Registers are specified as an enumerated
+ /// offset into the space. Other than 8-byte reads return the data right
+ /// justfied in the 64-bit returned value. 8-byte reads are only allowed
+ /// for offsets that are 8-byte aligned; 4-byte reads are allowed for any
+ /// 4-byte aligned offset.
+ ///
+ /// \retval me Return values other than 0 indicate some type of error in
+ /// the access as defined by the ModelError enumeration.
+ virtual ModelError
+ registerRead(const PoreRegisterOffset i_offset,
+ uint64_t& o_data,
+ const size_t i_size = 8) = 0;
+
+ /// Write a user-visible control or data register \e with side effects
+ ///
+ /// \param[in] i_offset The register offset (see below).
+ ///
+ /// \param[in] i_data The write data. For 4-byte writes the data is
+ /// right justified.
+ ///
+ /// \param[in] i_size The size in bytes (see below).
+ ///
+ /// In general the PORE supports both 4- and 8-byte access to the control
+ /// and data register space. Registers are specified as an enumerated
+ /// offset into the space. 4-byte writes expect the data right justfied in
+ /// the 64-bit input value. 8-byte writes are only allowed for offsets
+ /// that are 8-byte aligned; 4-byte writes are allowed for any 4-byte
+ /// aligned offset.
+ ///
+ /// \retval me Return values other than 0 indicate some type of error in
+ /// the access as defined by the ModelError enumeration.
+ virtual ModelError
+ registerWrite(const PoreRegisterOffset i_offset,
+ const uint64_t i_data,
+ const size_t i_size = 8) = 0;
+
+ /// Read a user-visible control or data register \e without side effects
+ ///
+ /// \param[in] i_offset The register offset (see below).
+ ///
+ /// \param[out] o_data The returned data. For 4-byte reads the data is
+ /// right justified.
+ ///
+ /// \param[in] i_size The size in bytes (see below).
+ ///
+ /// In general the PORE supports both 4- and 8-byte access to the control
+ /// and data register space. Registers are specified as an enumerated
+ /// offset into the space. Other than 8-byte reads return the data right
+ /// justfied in the 64-bit returned value. 8-byte reads are only allowed
+ /// for offsets that are 8-byte aligned; 4-byte reads are allowed for any
+ /// 4-byte aligned offset.
+ ///
+ /// \retval me Return values other than 0 indicate some type of error in
+ /// the access as defined by the ModelError enumeration.
+ virtual ModelError
+ registerReadRaw(const PoreRegisterOffset i_offset,
+ uint64_t& o_data,
+ const size_t i_size = 8) = 0;
+
+ /// Write a user-visible control or data register \e without side effects
+ ///
+ /// \param[in] i_offset The register offset (see below).
+ ///
+ /// \param[in] i_data The write data. For 4-byte writes the data is
+ /// right justified.
+ ///
+ /// \param[in] i_size The size in bytes (see below).
+ ///
+ /// In general the PORE supports both 4- and 8-byte access to the control
+ /// and data register space. Registers are specified as an enumerated
+ /// offset into the space. 4-byte writes expect the data right justfied in
+ /// the 64-bit input value. 8-byte writes are only allowed for offsets
+ /// that are 8-byte aligned; 4-byte writes are allowed for any 4-byte
+ /// aligned offset.
+ ///
+ /// \retval me Return values other than 0 indicate some type of error in
+ /// the access as defined by the ModelError enumeration.
+ virtual ModelError
+ registerWriteRaw(const PoreRegisterOffset i_offset,
+ const uint64_t i_data,
+ const size_t i_size = 8) = 0;
+
+ /// Enable or disable the HOOKI instruction
+ ///
+ /// \param[in] i_enable Either enable or disable the HOOKI instruction.
+ ///
+ /// The virtual HOOK instruction is disabled by default. This API enables
+ /// or disables the PoreModel to call out using the PoreModel::hook()
+ /// interface when it encounters a HOOKI instruction.
+ ///
+ /// \retval me Return values other than 0 indicate some type of error in
+ /// the method as defined by the ModelError enumeration.
+ virtual ModelError
+ enableHookInstruction(bool i_enable) = 0;
+
+ /// Enable or disable address-based hooks
+ ///
+ /// \param[in] i_enable Either enable or disable address-based hooks.
+ ///
+ /// Address-based hooks are disabled by default. This API enables or
+ /// disables the PoreModel to call out using the readHook(), writeHook()
+ /// and fetchHook() interfaces whenever the model is about to read, write
+ /// or fetch respectively.
+ ///
+ /// \retval me Return values other than 0 indicate some type of error in
+ /// the method as defined by the ModelError enumeration.
+ virtual ModelError
+ enableAddressHooks(bool i_enable) = 0;
+
+ /// Extract the PORE state for checkpointing
+ ///
+ /// \param[out] o_state A reference to a PoreState object to receive the
+ /// checkpointed state.
+ ///
+ /// This method checkpoints the state of a PORE engine into an abstract
+ /// PoreState object, in a way that allows the state to be later restored
+ /// with installState(). The state that is saved is only the PORE engine
+ /// state, and does not include any other state of the PORE virtual
+ /// environment.
+ ///
+ /// This method must be implemented in the derived class that implements
+ /// other virtual methods of the PoreModel. A simulation or software
+ /// model should be able to precisely recover to an arbitrary
+ /// state. Physical hardware may have limited abilities to do this due to
+ /// register side effects, read-only state etc., and may return an error
+ /// code if PORE engine is in a state that can't be restored.
+ ///
+ /// Note: The PORE engine must be in the hardware-stop state
+ /// before checkpointing in order to guarantee that the state can be
+ /// precisely saved and restored under all conditions.
+ ///
+ /// \retval me Normally 0 for success, but may be set by a dervied model
+ /// that is unable to satisfactorily extract the state for some reason.
+ virtual ModelError
+ extractState(PoreState& o_state) = 0;
+
+ /// Install a checkpointed state
+ ///
+ /// \param[in] i_state A PoreState object containing the entire visible
+ /// register state of the PORE.
+ ///
+ /// This method restores a PORE engine state checkpointed with
+ /// extractState(). The state that is restored is only the PORE engine
+ /// state. The PoreState object does not include any other state of the
+ /// PORE virtual environment.
+ ///
+ /// This method must be implemented in the derived class that implements
+ /// other virtual methods of the PoreModel. A simulation or software
+ /// model should be able to precisely recover to an arbitrary
+ /// state. Physical hardware may have limited abilities to do this due to
+ /// register side effects, read-only state etc., and may return an error
+ /// code if unable to restore the state from the PoreState object.
+ ///
+ /// \retval me Normally 0 for success, but may be set by a dervied model
+ /// that is unable to satisfactorily restore a state for some reason.
+ virtual ModelError
+ installState(const PoreState& i_state) = 0;
+
+ /// Force the PORE engine to branch (from a hook context)
+ ///
+ /// \param[in] i_address The address to branch to.
+ ///
+ /// This method is for use only by hooks, and only by address-based fetch
+ /// hooks and hooks attached to the HOOKI instruction. This method forces
+ /// the PORE engine to branch to an address specified in the \a i_address
+ /// parameter. This method is only defined on software simulated models,
+ /// and will not work on hardware models (including VHDL PORE models). To
+ /// change the PC from a stopped state use the setPc() method which will
+ /// work on all underlying models.
+ ///
+ /// The behavior varies based on the hook context:
+ ///
+ /// - For address-based fetch hooks, the conceptual model is that the hook
+ /// executes before the instruction that follows the hook. Practically
+ /// speaking, the hook may actually be invoked at the beginning of
+ /// instruction fetch. The derived PoreModel will ensure that any fetch
+ /// and execution of the instruction following the hook is cleanly
+ /// abandoned, and will instead go to fetch and execute the instruction at
+ /// \a i_address, including processing any fetch hooks on the new
+ /// target. The hook subroutine that invokes forceBranch() will be fully
+ /// executed before the forced branch.
+ ///
+ /// - For HOOKI instruction hooks the, the behavior is as if the HOOKI
+ /// instruction were an immediate branch to the absolute target. Again,
+ /// the hook subroutine that invokes forceBranch() will be fully executed
+ /// before the forced branch.
+ ///
+ /// If forceBranch() is called from any other context, the PoreModel will
+ /// return the ModelError ME_ILLEGAL_FORCED_BRANCH. Even so, this API is
+ /// fraught with potential problems, e.g. ping-pong livelocks between
+ /// fetch hooks. forceBranch() should only be used for simple,
+ /// straightforward control flow modifications.
+ ///
+ /// \retval Either 0 for SUCCESS, ME_ILLEGAL_FORCED_BRANCH or any other
+ /// non-0 ModelError that might be signalled during execution of the
+ /// method.
+ virtual ModelError
+ forceBranch(const PoreAddress& i_address) = 0;
+
+
+ //////////////////// PoreInterface Methods /////////////////////////
+
+protected:
+
+ /// Master a PIB transaction to the virtual environment
+ ///
+ /// \param[in,out] io_transaction The abstract PIB transaction
+ ///
+ /// PIB/PCB transaction status is returned in the \a iv_pcbReturnCode
+ /// field of the transaction. A legal API call will always succeed, even
+ /// if the underlying bus transaction fails. If the transaction is
+ /// illegal in some way (indicating an issue in the derived PoreModel) then
+ /// this must be trapped by the PoreInterface.
+ void
+ pibMaster(PibTransaction& io_transaction);
+
+ /// Master an OCI transaction to the virtual environment
+ ///
+ /// \param[in,out] io_transaction The abstract OCI transaction
+ ///
+ /// OCI transaction status is returned in the \a iv_ociReturnCode field of
+ /// the transaction. A legal API call will always succeed, even if the
+ /// underlying bus transaction fails. If the transaction is illegal in
+ /// some way (indicating an issue in the derived PoreModel) then this must
+ /// be trapped by the PoreInterface.
+ void
+ ociMaster(OciTransaction& io_transaction);
+
+ /// Implement the WAIT instruction
+ ///
+ /// \param[in] i_count The number of PORE cycles to wait.
+ ///
+ /// The PoreModel has no notion of time, so it requires the environment to
+ /// model WAIT. The hardware treats WAIT 0 as a special HALT instruction,
+ /// however the concrete model still must still invoke the wait() method
+ /// in this case to inform the abstract model that the PORE has halted
+ /// (since this generates a hardware interrupt). Since WAIT can not fail
+ /// in the hardware, any errors in the implementation of wait() must be
+ /// handled by the PoreInterface.
+ void
+ wait(const uint32_t i_count);
+
+ /// Implement the HOOKI instruction
+ ///
+ /// \param[in] i_address The effective address of the HOOKI instruction.
+ ///
+ /// \param[in] i_hook The low-order 24 bits of the HOOKI instruction, used
+ /// to index the hook routine that will process the hook.
+ ///
+ /// \param[in] i_parameter A 64-bit parameter for the hook routine.
+ ///
+ /// The HOOKI instruction allows the PORE code to invoke a fixed set of
+ /// hooks indexed by a 24-bit integer code, passing each hook routine a
+ /// 64-bit parameter. The underlying hardware model has no dependency on
+ /// the outcome of running a hook, therefore any errors in hook processing
+ /// must be handled by the PoreInterface.
+ void
+ hookInstruction(const PoreAddress& i_address,
+ const uint32_t i_hook,
+ const uint64_t i_parameter);
+
+ /// Notify the environment of a data read
+ ///
+ /// \param[in] i_address The effective PoreAddress of the data read.
+ ///
+ /// This method allows the environment to hook data reads. For direct
+ /// memory accesses, this method is called immediately before a bus
+ /// transaction is generated to fetch the data at the given effective
+ /// address. For indirect PIB transactions, this method is invoked prior
+ /// to the I2C transaction that actually reads the data from the I2C
+ /// memory. The underlying hardware model has no dependency on the outcome
+ /// of running a hook, therefore any errors in hook processing must be
+ /// handled by the PoreInterface.
+ void
+ hookRead(const PoreAddress& i_address);
+
+ /// Notify the environment of a data write
+ ///
+ /// \param[in] i_address The effective PoreAddress of the data write.
+ ///
+ /// This method allows the environment to hook data writes. For direct
+ /// memory accesses, this method is called immediately before a bus
+ /// transaction is generated to store the data at the given effective
+ /// address. For indirect PIB transactions, this method is invoked prior
+ /// to the I2C transaction that actually writes the data to the I2C
+ /// memory. The underlying hardware model has no dependency on the outcome
+ /// of running a hook, therefore any errors in hook processing must be
+ /// handled by the PoreInterface.
+ void
+ hookWrite(const PoreAddress& i_address);
+
+ /// Notify the environment of an instruction fetch
+ ///
+ /// \param[in] i_address The effective PoreAddress of the instruction.
+ ///
+ /// This method allows the environment to hook instruction fetches, where
+ /// an instruction fetch refers to reading the first 4 (of potentially 12)
+ /// bytes that comprise an instruction for the purposes of instruction
+ /// execution. For direct memory accesses, this method is called
+ /// immediately before a bus transaction is generated to read the
+ /// instruction data at the given effective address. For indirect PIB
+ /// transactions, this method is invoked prior to the I2C transaction that
+ /// actually fetches the data from the I2C memory. The underlying hardware
+ /// model has no dependency on the outcome of running a hook, therefore
+ /// any errors in hook processing must be handled by the PoreInterface.
+ void
+ hookFetch(const PoreAddress& i_address);
+
+ /// Notify the environment of the error interrupt
+ ///
+ /// This method must be invoked by the deribed PoreModel whenever the
+ /// execution of an instruction would pulse the PORE hardware \a
+ /// tp_por_error_out signal.
+ void
+ errorIntr(void);
+
+ /// Notify the environment of the fatal error interrupt
+ ///
+ /// This method must be invoked by the derived PoreModel whenever the
+ /// execution of an instruction would pulse the PORE hardware \a
+ /// tp_por_fatal_error_out signal.
+ void
+ fatalErrorIntr(void);
+
+
+ ////////////////////////////// Creators //////////////////////////////
+
+public:
+
+ /// Create the PoreModel base class
+ ///
+ /// The PoreModel is defined to be in the restart (scan-flush) state at
+ /// the end of constructing the model.
+ ///
+ /// \param[in] i_ibufId The IBUF ID (PORE type) of the model.
+ ///
+ /// \param[in] i_interface A pointer back to the PoreInterface that
+ /// created this model.
+ PoreModel(const PoreIbufId i_ibufId, PoreInterface* i_interface);
+
+ virtual ~PoreModel();
+
+
+ ////////////////////////// Implementation ////////////////////////////
+
+protected:
+
+ /// The IBUF ID (engine type) of the PORE being modeled
+ PoreIbufId iv_ibufId;
+
+private:
+
+ /// The most recent ModelError generated by the model or by calls of
+ /// modelError(), or 0 for no error.
+ ModelError iv_modelError;
+
+ /// The total number of instructions executed since the PoreModel
+ /// was created, or since the last restart() operation.
+ uint64_t iv_instructions;
+
+ /// The most recent stop code provided in a call of stop(), or 0 if the
+ /// model is not stopped.
+ int iv_stopCode;
+
+ /// Pointer back to the virtual interface containing this hardware model.
+ PoreInterface* iv_interface;
+
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ PoreModel(const PoreModel& i_rhs);
+ PoreModel& operator=(const PoreModel& i_rhs);
+};
+
+#endif // __VSBE_POREMODEL_H
diff --git a/src/usr/pore/poreve/model/poreregister.C b/src/usr/pore/poreve/model/poreregister.C
new file mode 100644
index 000000000..7be840b4c
--- /dev/null
+++ b/src/usr/pore/poreve/model/poreregister.C
@@ -0,0 +1,295 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/model/poreregister.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// $Id: poreregister.C,v 1.5 2011/08/03 17:59:00 bcbrock Exp $
+
+/// \file poreregister.C
+/// \brief The PoreRegister and PoreRegisterWritable classes
+
+#include "poreinterface.H"
+
+using namespace vsbe;
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreRegister
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////// Creators //////////////////////////////
+
+PoreRegister::PoreRegister(PoreInterface* i_interface,
+ const PoreRegisterEncoding i_encoding) :
+ iv_interface(i_interface),
+ iv_encoding(i_encoding)
+{
+}
+
+
+PoreRegister::~PoreRegister()
+{
+}
+
+
+uint64_t
+PoreRegister::read() const
+{
+ uint64_t data;
+ ModelError me;
+ PoreRegisterOffset offset = PORE_REGISTER_MAP[iv_encoding];
+
+ switch (iv_encoding) {
+
+ case PORE_D0:
+ case PORE_D1:
+ case PORE_A0:
+ case PORE_A1:
+ case PORE_EMR:
+ case PORE_ETR:
+ case PORE_IFR:
+
+ // These are read as 64-bit registers in the model
+
+ me = iv_interface->registerRead(offset, data);
+ break;
+
+ case PORE_P0:
+ case PORE_P1:
+ case PORE_CTR:
+ case PORE_SPRG0:
+
+ // These registers are <= 32 bits and stored right-justified in the
+ // high-order 32 bits of the 64-bit registers. In every case the
+ // hardware specification specifies that unused bits on the left read
+ // as 0.
+
+ me = iv_interface->registerRead(offset, data);
+ data >>= 32;
+ break;
+
+ case PORE_PC:
+
+ // The PC is read as the low-order 48 bits of the status register.
+
+ me = iv_interface->registerRead(offset, data);
+ data &= 0xffffffffffffull;
+ break;
+
+ case PORE_CIA:
+
+ // The CIA is obtained from the high-order 48 bits of the DBG1
+ // register.
+
+ me = iv_interface->registerRead(offset, data);
+ data >>= 16;
+ break;
+
+ default:
+ me = ME_BUG;
+ break;
+ }
+ if (me != 0) {
+ iv_interface->modelError(me);
+ }
+ return data;
+}
+
+
+PoreRegister::operator uint64_t () const
+{
+ return read();
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreRegisterWritable
+////////////////////////////////////////////////////////////////////////////
+
+PoreRegisterWritable::
+PoreRegisterWritable(PoreInterface* i_interface,
+ const PoreRegisterEncoding i_encoding) :
+ PoreRegister(i_interface, i_encoding)
+{
+}
+
+
+PoreRegisterWritable::~PoreRegisterWritable()
+{
+}
+
+
+uint64_t
+PoreRegisterWritable::write(const uint64_t i_data)
+{
+ ModelError me;
+ PoreRegisterOffset offset = PORE_REGISTER_MAP[iv_encoding];
+
+ switch (iv_encoding) {
+
+ case PORE_D0:
+ case PORE_D1:
+
+ // These are written as 64-bit registers in the model
+
+ me = iv_interface->registerWrite(offset, i_data);
+ break;
+
+ case PORE_A0:
+ case PORE_A1:
+
+ // The programmer-writable portion of A0 and A1 are the low-order
+ // 46 bits.
+
+ me = iv_interface->registerWrite(offset, i_data & 0x3fffffffffffull);
+ break;
+
+ case PORE_P0:
+ case PORE_P1:
+
+ // The programmer-visible portion is bits 25:31, the remainder is
+ // undefined.
+
+ me = iv_interface->registerWrite(offset, (i_data & 0x7f) << 32);
+ break;
+
+ case PORE_CTR:
+
+ // The programmer-visible portion is bits 8:31, the remainder is
+ // undefined.
+
+ me = iv_interface->registerWrite(offset, (i_data & 0xffffff) << 32);
+ break;
+
+ case PORE_EMR:
+
+ // The programmer-visible portion is bits 0:20
+
+ me = iv_interface->registerWrite(offset,
+ i_data & 0xfffff80000000000ull);
+ break;
+
+ case PORE_SPRG0:
+
+ // These register moves the low-order 32 bits of the data to the
+ // high-order bits of the target.
+
+ me = iv_interface->registerWrite(offset, (i_data & 0xffffffff) << 32);
+ break;
+
+ case PORE_IFR:
+
+ // Only bits 48:55 of the IFR (the ALU flags) are writable.
+
+ me = iv_interface->registerWrite(offset, i_data & 0xff00ull);
+ break;
+
+ case PORE_ETR:
+
+ // Only the low-order 32 bits are writable
+
+ me = iv_interface->registerWrite(PORE_EXE_TRIGGER_HI, i_data, 4);
+ break;
+
+ default:
+ me = ME_BUG;
+ break;
+ }
+ if (me != 0) {
+ iv_interface->modelError(me);
+ }
+ return i_data;
+}
+
+
+uint64_t
+PoreRegisterWritable::operator=(const uint64_t& i_data)
+{
+ return write(i_data);
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreDataBuffer
+////////////////////////////////////////////////////////////////////////////
+
+PoreDataBuffer::PoreDataBuffer(PoreInterface* i_interface,
+ const PoreRegisterEncoding i_encoding) :
+ PoreRegisterWritable(i_interface, i_encoding)
+{
+}
+
+
+PoreDataBuffer::~PoreDataBuffer()
+{
+}
+
+
+bool
+PoreDataBuffer::isBitSet(const uint32_t i_bit)
+{
+ return (read() & BE64_BIT(i_bit)) != 0;
+}
+
+
+bool
+PoreDataBuffer::isBitClear(const uint32_t i_bit)
+{
+ return (read() & BE64_BIT(i_bit)) == 0;
+}
+
+
+uint64_t
+PoreDataBuffer::extractToRight(const uint32_t i_start,
+ const uint32_t i_len)
+{
+ return BE64_GET_FIELD(read(), i_start, (i_start + i_len - 1));
+}
+
+
+// This needs to be replicated here for obscure C++ reasons
+uint64_t
+PoreDataBuffer::operator=(const uint64_t& i_data)
+{
+ return write(i_data);
+}
+
+
+uint64_t
+PoreDataBuffer::setBit(const uint32_t i_bit)
+{
+ return write(read() | BE64_BIT(i_bit));
+}
+
+
+uint64_t
+PoreDataBuffer::clearBit(const uint32_t i_bit)
+{
+ return write(read() & ~BE64_BIT(i_bit));
+}
+
+uint64_t
+PoreDataBuffer::insertFromRight(const uint64_t i_data,
+ const uint32_t i_start,
+ const uint32_t i_len)
+{
+ return write(BE64_SET_FIELD(read(), i_start, (i_start + i_len - 1),
+ i_data));
+}
diff --git a/src/usr/pore/poreve/model/poreregister.H b/src/usr/pore/poreve/model/poreregister.H
new file mode 100644
index 000000000..24147365f
--- /dev/null
+++ b/src/usr/pore/poreve/model/poreregister.H
@@ -0,0 +1,275 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/model/poreregister.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_POREREGISTER_H
+#define __VSBE_POREREGISTER_H
+
+// $Id: poreregister.H,v 1.2 2011/08/03 17:59:00 bcbrock Exp $
+
+/// \file poreregister.H
+/// \brief The PoreRegister and PoreRegisterWritable classes
+
+#include <stdint.h>
+
+#include "poreconstants.H"
+
+namespace vsbe {
+
+ class PoreRegister;
+ class PoreRegisterWritable;
+ class PoreDataBuffer;
+ class PoreInterface;
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreRegister
+////////////////////////////////////////////////////////////////////////////
+
+/// An abstract PORE programmer-visible register model
+///
+/// This class is introduced to provide abstract register models that are easy
+/// to program for user code (e.g., hooks), by making the register appear to
+/// be a data member of the PoreInterface, but leaving the implementation to
+/// the underlying PoreModel. This is necessary in part because there is not
+/// always a direct map between the PORE hardware register and the
+/// programmer-visible register (or abstract register like CIA).
+///
+/// Two types of register are supported here:
+///
+/// - True programmer-visible registers like D0, A0, P0, PC
+/// - "Abstract" registers introduced to simplify hook programming like CIA
+///
+/// The register values manipulated by the PoreRegister associated with true
+/// programmer visible registers are always the programmer-visible register
+/// contents. Reading the register always returns the value as if the
+/// register were moved to a 64-bit data register inside the engine. Writing
+/// the register updates the underlying hardware model as if the register were
+/// updated by a move from a 64-bit data register.
+///
+/// The PoreRegister defines a conversion operator to a uint64_t. This allows
+/// the register object to be used as if it were a uint64_t data member of the
+/// PoreInterface. Note that for registers smaller than 64 bits the data will
+/// be (for reads), or is expected to be (for writes), right justfied in the
+/// 64 bit input or result.
+///
+/// When the PoreRegister instances are defined as data members of
+/// PoreInterface, each instance is parameterized with the information
+/// necessary to transform an access of the abstract register into the
+/// register interface calls of the PoreModel. Note that in certain cases it
+/// may not be possible to use the abstract register directly in an expression
+/// because the usage is ambiguous to the compiler. These problems can
+/// be solved either by using temporary variables to disambiguate the usage,
+/// or by explicitly using the read() methods of the PoreRegister
+/// objects.
+///
+/// All registers have read access and read() methods. Most are actually
+/// implemeted as the PoreRegisterWritable subclass that has write access and
+/// a write method as well.
+
+class
+vsbe::PoreRegister {
+
+public:
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ /// Create a PoreRegister
+ ///
+ /// \param[in] i_interface A pointer to the parent PoreInterface object that
+ /// implements the underlying registerRead() and registerWrite() methods.
+ ///
+ /// \param[in] i_register A value from the enumeration
+ /// PoreRegisterEncodingore identifying the register.
+ PoreRegister(PoreInterface* i_interface,
+ const PoreRegisterEncoding i_register);
+
+ virtual ~PoreRegister();
+
+ ///////////////////////////// Accessors //////////////////////////////
+
+ /// Implement the PoreRegister register read
+ ///
+ /// Note that if the embedded call of PoreInterface::registerRead() fails
+ /// it is considered a bug in the model.
+ ///
+ /// \retval value The current register value, right justified in the
+ /// return value.
+ virtual uint64_t read() const;
+
+ /// Get the register value as a conversion (cast) using read().
+ virtual operator uint64_t () const;
+
+
+ ////////////////////////// Implementation ////////////////////////////
+
+protected:
+
+ /// The parent PoreInterface object
+ PoreInterface* iv_interface;
+
+ /// The PORE ISA encoding of register
+ PoreRegisterEncoding iv_encoding;
+
+ ////////////////////////// Safety ////////////////////////////
+
+private:
+
+ PoreRegister(const PoreRegister& i_rhs);
+ PoreRegister& operator=(PoreRegister& i_rhs);
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreRegisterWritable
+////////////////////////////////////////////////////////////////////////////
+
+/// A writable PoreRegister
+///
+/// This subclass extends the PoreRegister class by the addition of write
+/// access and a write() method.
+
+class
+vsbe::PoreRegisterWritable : public PoreRegister {
+
+public:
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ /// Create a PoreRegisterWritable
+ ///
+ /// \param[in] i_interface A pointer to the parent PoreInterface object that
+ /// implements the underlying registerRead() and registerWrite() methods.
+ ///
+ /// \param[in] i_register A value from the enumeration
+ /// PoreRegisterEncoding identifying the register.
+ PoreRegisterWritable(PoreInterface* i_interface,
+ const PoreRegisterEncoding i_register);
+
+ virtual ~PoreRegisterWritable();
+
+
+ //////////////////////////// Manipulators ////////////////////////////
+
+ /// Implement the PoreRegister register write
+ ///
+ /// \param[in] i_data The data to be written to the register
+ ///
+ /// For registers smaller than 64 bits, the low-order bits of \a i_data
+ /// are inserted into the hardware register. Note that if the embedded
+ /// call of PoreInterface::registerWritw() fails it is considered a bug in
+ /// the model.
+ ///
+ /// \retval data This method returns its input \a data.
+ virtual uint64_t write(const uint64_t i_data);
+
+ /// Assign a value to a register using operator=(). See write().
+ virtual uint64_t operator=(const uint64_t& i_data);
+
+
+ ////////////////////////// Safety ////////////////////////////
+
+private:
+
+ PoreRegisterWritable(const PoreRegisterWritable& i_rhs);
+ PoreRegisterWritable& operator=(PoreRegisterWritable& i_rhs);
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreDataBuffer
+////////////////////////////////////////////////////////////////////////////
+
+/// A PoreRegister as an ecmdDataBuffer
+///
+/// This subclass extends the PoreRegisterWritable class by the addition of
+/// selected methods of the ecmdDataBuffer, to provide a familiar and
+/// convenient API for manipulating data in the PoreVe. Only the 64-bit data
+/// registers D0 and D1 are implemented using this class.
+///
+/// Note that the eCmd-like methods are all implemented in functional form for
+/// simplicty, and operate on uint64_t data values exclusively. There is no
+/// error checking for bit positions, which are assumed to fall with the range
+/// 0:63.
+
+class
+vsbe::PoreDataBuffer : public PoreRegisterWritable {
+
+public:
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ /// Create a PoreDataBuffer
+ ///
+ /// \param[in] i_interface A pointer to the parent PoreInterface object that
+ /// implements the underlying registerRead() and registerWrite() methods.
+ ///
+ /// \param[in] i_register A value from the enumeration
+ /// PoreRegisterEncoding identifying the register.
+ PoreDataBuffer(PoreInterface* i_interface,
+ const PoreRegisterEncoding i_register);
+
+ virtual ~PoreDataBuffer();
+
+
+ //////////////////////////// Accessors ////////////////////////////
+
+ /// Return \a true if bit \a i_bit is set, otherwise \a false
+ virtual bool isBitSet(const uint32_t i_bit);
+
+ /// Return \a true if bit \a i_bit is clear, otherwise \a false
+ virtual bool isBitClear(const uint32_t i_bit);
+
+ /// Extract \a i_len bits from \a i_start and right justify into a uint64_t
+ virtual uint64_t extractToRight(const uint32_t i_start,
+ const uint32_t i_len);
+
+ using PoreRegister::operator uint64_t;
+
+
+ //////////////////////////// Manipulators ////////////////////////////
+
+ /// Assign a value to a register using operator=(). See write().
+ virtual uint64_t operator=(const uint64_t& i_data);
+
+ /// Set bit \a i_bit and return the new 64-bit value
+ virtual uint64_t setBit(const uint32_t i_bit);
+
+ /// Clear bit \a i_bit and return the new 64-bit value
+ virtual uint64_t clearBit(const uint32_t i_bit);
+
+ /// Insert \a i_len low-order bits of \a i_data at \a i_start and return
+ /// the new 64-bit value
+ virtual uint64_t insertFromRight(const uint64_t i_data,
+ const uint32_t i_start,
+ const uint32_t i_len);
+
+
+ ////////////////////////// Safety ////////////////////////////
+
+private:
+
+ PoreDataBuffer(const PoreDataBuffer& i_rhs);
+ PoreDataBuffer& operator=(PoreDataBuffer& i_rhs);
+};
+
+#endif // __VSBE_POREREGISTER_H
diff --git a/src/usr/pore/poreve/model/porestate.C b/src/usr/pore/poreve/model/porestate.C
new file mode 100644
index 000000000..b3ce8a087
--- /dev/null
+++ b/src/usr/pore/poreve/model/porestate.C
@@ -0,0 +1,93 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/model/porestate.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// $Id: porestate.C,v 1.2 2011/10/13 10:04:32 haver Exp $
+
+/// \file porestate.C
+/// \brief A structure defining the state of a PORE engine for
+/// checkpoint/restart purposes.
+
+#include "porestate.H"
+#include <string.h>
+
+using namespace vsbe;
+
+
+PoreState::PoreState()
+{
+ // Ensure that reserved/free space is always 0 such that we
+ // can do memcmp.
+ memset(state, 0, sizeof(state));
+}
+
+
+PoreState::~PoreState()
+{
+}
+
+
+ModelError
+PoreState::get(const PoreRegisterOffset i_offset, uint64_t& o_reg) const
+{
+ ModelError me;
+ int i;
+
+ if ((i_offset >= SIZEOF_PORE_STATE) || ((i_offset % 8) != 0)) {
+ me = ME_PORE_STATE_ERROR;
+ } else {
+
+ me = ME_SUCCESS;
+ o_reg = 0;
+ for (i = 0; i < 8; i++) {
+ o_reg <<= 8;
+ o_reg |= state[i_offset + i];
+ }
+ }
+
+ return me;
+}
+
+
+ModelError
+PoreState::put(const PoreRegisterOffset i_offset, const uint64_t i_reg)
+{
+ ModelError me;
+ int i;
+ uint64_t reg;
+
+ if ((i_offset >= SIZEOF_PORE_STATE) || ((i_offset % 8) != 0)) {
+ me = ME_PORE_STATE_ERROR;
+ } else {
+
+ me = ME_SUCCESS;
+ reg = i_reg;
+ for (i = 7; i >= 0; i--) {
+ state[i_offset + i] = (reg & 0xff);
+ reg >>= 8;
+ }
+ }
+
+ return me;
+}
+
+
+
diff --git a/src/usr/pore/poreve/model/porestate.H b/src/usr/pore/poreve/model/porestate.H
new file mode 100644
index 000000000..914335ed2
--- /dev/null
+++ b/src/usr/pore/poreve/model/porestate.H
@@ -0,0 +1,108 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/model/porestate.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_PORE_STATE_H
+#define __VSBE_PORE_STATE_H
+
+// $Id: porestate.H,v 1.1 2011/06/12 13:14:03 bcbrock Exp $
+
+/// \file porestate.H
+/// \brief A structure defining the state of a PORE engine for
+/// checkpoint/restart purposes.
+
+#include "poreinterface.H"
+
+namespace vsbe {
+
+ class PoreState;
+};
+
+
+/// The state of a PORE engine
+///
+/// The PoreState class represents the state of the PORE engine for
+/// checkpoint/restore purposes. The state is stored as an endian-neutral
+/// checkpoint of the register space of the PORE engine, therefore the object
+/// can be saved and restored to/from a file regardless of the endianess of
+/// the save and restore hosts. Methods are provided to access the hardware
+/// register images using the PoreRegisterOffset enumeration offsets.
+///
+/// This object is used as a parameter of the PoreInterface::extractState()
+/// and poreInterface::installState() methods. Please see the documentation
+/// of those methods for information on how the PoreState is checkpointed and
+/// restored.
+
+class
+vsbe::PoreState {
+
+public:
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ PoreState();
+
+ virtual ~PoreState();
+
+
+ ///////////////////////////// Accessors //////////////////////////////
+
+ /// Get a register image from the state
+ ///
+ /// \param[in] i_offset The PoreRegisterOffset of the requested register.
+ ///
+ /// \param[out] o_reg The requested register value obtained from the state.
+ ///
+ /// \retval me Either 0 for success, or a ModelError error code.
+ virtual ModelError
+ get(const PoreRegisterOffset i_offset, uint64_t& o_reg) const;
+
+
+ ///////////////////////////// Manipulators ///////////////////////////
+
+ /// Put a register image into the state
+ ///
+ /// \param[in] i_offset The PoreRegisterOffset of the requested register.
+ ///
+ /// \param[in] i_reg The new value of the requested register to store in
+ /// the state. value.
+ ///
+ /// \retval me Either 0 for success, or a ModelError error code.
+ virtual ModelError
+ put(const PoreRegisterOffset i_offset, const uint64_t i_reg);
+
+
+ ////////////////////////// Implementation ////////////////////////////
+
+protected:
+
+ /// The register state
+ uint8_t state[SIZEOF_PORE_STATE];
+
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ PoreState(const PoreState& rhs);
+ PoreState& operator=(const PoreState& rhs);
+};
+
+#endif // __VSBE_PORE_STATE
diff --git a/src/usr/pore/poreve/model/transaction.C b/src/usr/pore/poreve/model/transaction.C
new file mode 100644
index 000000000..92c5692e9
--- /dev/null
+++ b/src/usr/pore/poreve/model/transaction.C
@@ -0,0 +1,90 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/model/transaction.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// $Id: transaction.C,v 1.1 2011/05/06 23:29:00 bcbrock Exp $
+
+/// \file transaction.C
+/// \brief PORE abstract bus transactions
+
+#include "transaction.H"
+
+using namespace vsbe;
+
+
+// There are no 'obvious' constructors for these classes; Likely the PORE
+// model will build one of each type and resuse it over and over, changing the
+// fields on each use.
+
+Transaction::Transaction()
+{
+}
+
+
+Transaction::~Transaction()
+{
+}
+
+
+PibTransaction::PibTransaction()
+{
+}
+
+
+PibTransaction::~PibTransaction()
+{
+}
+
+
+ModelError
+PibTransaction::busError(ModelError i_me)
+{
+ iv_modelError = i_me;
+ if (i_me == ME_SUCCESS) {
+ iv_pcbReturnCode = PCB_SUCCESS;
+ } else {
+ iv_pcbReturnCode = PCB_TIMEOUT;
+ }
+ return i_me;
+}
+
+
+OciTransaction::OciTransaction()
+{
+}
+
+
+OciTransaction::~OciTransaction()
+{
+}
+
+
+ModelError
+OciTransaction::busError(ModelError i_me)
+{
+ iv_modelError = i_me;
+ if (i_me == ME_SUCCESS) {
+ iv_ociReturnCode = OCI_SUCCESS;
+ } else {
+ iv_ociReturnCode = OCI_BUS_ERROR;
+ }
+ return i_me;
+}
diff --git a/src/usr/pore/poreve/model/transaction.H b/src/usr/pore/poreve/model/transaction.H
new file mode 100644
index 000000000..39fd0b135
--- /dev/null
+++ b/src/usr/pore/poreve/model/transaction.H
@@ -0,0 +1,251 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/model/transaction.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_TRANSACTION_H
+#define __VSBE_TRANSACTION_H
+
+// $Id: transaction.H,v 1.4 2011/06/06 15:35:15 bcbrock Exp $
+
+/// \file transaction.H
+/// \brief PORE abstract bus transactions
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "modelerror.H"
+
+
+namespace vsbe {
+
+ class Transaction;
+ class PibTransaction;
+ class OciTransaction;
+
+
+ /// \defgroup pore_transaction_modes PORE Transaction Modes
+ ///
+ /// Each PORE transaction is tagged with a one-hot mask indicating whether
+ /// the transaction is a read, write or instruction fetch. The Slave
+ /// and MemoryImage models also include a bit-set of these masks to
+ /// indicate whether the Slave or MemoryImage supports the indicated
+ /// access.
+ ///
+ /// @{
+
+ /// A data read; Allow read access
+ const int ACCESS_MODE_READ = 0x1;
+ /// A data write; Allow write access
+ const int ACCESS_MODE_WRITE = 0x2;
+ /// An instruction fetch; Allow execute access
+ const int ACCESS_MODE_EXECUTE = 0x4;
+
+ /// @}
+
+ /// The byte size of a transaction on the bus
+ const int TRANSACTION_SIZE_IN_BYTES = 0x8;
+
+ /// \enum PcbReturnCode
+ ///
+ /// This enumeration follows the 3-bit return code as specified in the
+ /// Pervasive Workbook
+ enum PcbReturnCode {
+ PCB_SUCCESS = 0,
+ PCB_RESOURCE_OCCUPIED = 1,
+ PCB_CHIPLET_OFFLINE = 2,
+ PCB_PARTIAL_GOOD = 3,
+ PCB_ADDRESS_ERROR = 4,
+ PCB_CLOCK_ERROR = 5,
+ PCB_PACKET_ERROR = 6,
+ PCB_TIMEOUT = 7
+ };
+
+
+ /// \enum OciReturnCode
+ ///
+ /// These return codes are abstractions; The OCI_BUS_ERROR is a catch-all
+ /// for now.
+ enum OciReturnCode {
+ OCI_SUCCESS = 0,
+ OCI_BUS_ERROR = 1
+ };
+};
+
+
+/// PORE abstract transaction
+///
+/// This abstract transaction model is loosely based on the Simics model of a
+/// 'generic transaction', plus experience from the PMX model. It takes
+/// advantage of the fact that (currently) both the PIB and OCI interfaces use
+/// 32-bit addresses and (maximum) 8-byte data. The Pore model supports
+/// separate interfaces for PIB and OCI, and the base Transaction is an
+/// abstract class that is subclassed for PIB and OCI error reporting
+/// purposes.
+///
+/// The Transaction is part of the pure abstract PORE model, and is not tied
+/// to any particular virtual environment. The Transaction is originaly
+/// generated within the PoreModel, moves through the virtual environment, and
+/// eventually returns to the PoreModel with read data (for reads) and return
+/// codes. For simplicity all of the data members are declared public, and
+/// comments with the members indicate which system element is responsible for
+/// setting them and when.
+
+class
+vsbe::Transaction {
+
+public:
+
+ ///////////////////////// Abstract Interface /////////////////////////
+
+ /// Install \a i_me as the \a modelError field of the transaction and also
+ /// insert a bus-model specific error code.
+ ///
+ /// \param[in] i_me The ModelError associated with this generic bus error.
+ /// If \a i_me != ME_SUCCESS (0) then this method sets a bus-specific
+ /// error code in the transaction. If \a i_me == ME_SUCCESS (0) then this
+ /// method clears the bus-specific error code in the transaction.
+ ///
+ /// This method allows the common Bus model or memory models to signal a
+ /// generic catostrophic error (e.g., no slave or installed memory maps
+ /// the address) without knowing the derived type of the Transaction. The
+ /// \a i_me provides as a more descriptive reason for the bus error.
+ ///
+ /// \retval i_me This method returns its input parameter, \a i_me.
+ virtual ModelError
+ busError(const ModelError i_me) = 0;
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ Transaction();
+ virtual ~Transaction();
+
+ ////////////////////////// Implementation ////////////////////////////
+
+ /// The access mode (one of the MODE_* constants) set by PoreModel when
+ /// the transaction is mastered.
+ int iv_mode;
+
+ /// The 32-bit physical bus address, set by PoreModel when the transaction
+ /// is mastered.
+ uint32_t iv_address;
+
+ /// The 64-bit data, set by PoreModel for writes, and by the virtual
+ /// environment for reads.
+ ///
+ /// Data is manipulated by the PORE models in host byte order. The memory
+ /// models must translate host byte order to and from Big-Endian ordering
+ /// used in the PORE memory implementations. This implies that for
+ /// transaction sizes less than 8 bytes (which are all transactions for
+ /// now), the data is right justified in the data field, and can be
+ /// interpreted as if the hardware had loaded or stored an unsigned
+ /// integer of the given \a size.
+ uint64_t iv_data;
+
+ /// A PORE model error code
+ ///
+ /// The virtual environment is responsible for setting the \a modelError
+ /// for every transaction to a value selected from the ModelError
+ /// enumeration.
+ ModelError iv_modelError;
+
+ /// The address offset within the bus slave
+ ///
+ /// This field is added for the convenience of bus/slave models. It is
+ /// designed as a place for the bus/slave model to store the offset of the
+ /// addressed register/memory from a base address of a memory region or
+ /// set of registers. The PORE bus masters ignore this field. The PORE
+ /// bus slaves expect the environment to set this before sending a
+ /// Transaction into the PIB and OCI slaves.
+ uint32_t iv_offset;
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ Transaction(const Transaction& rhs);
+ Transaction& operator=(const Transaction& rhs);
+
+};
+
+
+/// Refine the Transaction for PIB/PCB-specific error reporting
+
+class
+vsbe::PibTransaction : public vsbe::Transaction {
+
+public:
+
+ ///////////////////////// Abstract Interface /////////////////////////
+
+ /// For the PIB bus, a bus error is treated as a PCB_TIMEOUT. See
+ /// Transaction::busError() for further details.
+ virtual ModelError busError(const ModelError i_me);
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ PibTransaction();
+ virtual ~PibTransaction();
+
+ ////////////////////////// Implementation ////////////////////////////
+
+ /// The PIB/PCB return code associated with the transaction, set by the
+ /// memory subsystem on every operation.
+ PcbReturnCode iv_pcbReturnCode;
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ PibTransaction(const PibTransaction& rhs);
+ PibTransaction& operator=(const PibTransaction& rhs);
+};
+
+
+/// Refine the Transaction for OCI-specific error reporting
+
+class
+vsbe::OciTransaction : public vsbe::Transaction {
+
+public:
+
+ ///////////////////////// Abstract Interface /////////////////////////
+
+ /// For the OCI bus, a bus error is treated as the generic OCI_BUS_ERROR.
+ /// See Transaction::busError() for further details.
+ virtual ModelError busError(const ModelError i_me);
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ OciTransaction();
+ virtual ~OciTransaction();
+
+ ////////////////////////// Implementation ////////////////////////////
+
+ /// The OCI return code associated with the transaction, set by the
+ /// memory subsystem on every operation.
+ OciReturnCode iv_ociReturnCode;
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ OciTransaction(const OciTransaction& rhs);
+ OciTransaction& operator=(const OciTransaction& rhs);
+};
+
+#endif // __VSBE_TRANSACTION_H
diff --git a/src/usr/pore/poreve/pore_model/ibuf/pore_bus.c b/src/usr/pore/poreve/pore_model/ibuf/pore_bus.c
new file mode 100644
index 000000000..7f8c2af27
--- /dev/null
+++ b/src/usr/pore/poreve/pore_model/ibuf/pore_bus.c
@@ -0,0 +1,934 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/pore_model/ibuf/pore_bus.c $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+/******************************************************************************
+ *
+ * Virtual PORe Engine
+ *
+ *****************************************************************************/
+
+/**
+ * 24-bit address:
+ * 11.1111.1111.2222
+ * 0123.4567.8901.2345.6789.0123
+ * || Mcase, ChipletId ...
+ * ||
+ * |`0: PIB_base_0
+ * | PIB_base_1
+ * |
+ * `0: PIB
+ * 1: Memory (fi2c when used as SBE or OCI otherwise)
+ * |
+ * ` 0: OCI_base_0 & MEM_RELOC
+ * 1: OCI_base_1 & MEM_RELOC
+ */
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pore_regs.h"
+#include "pore_model.h"
+#include "pore_ibuf.h"
+
+#define I2C_COMMAND_COMPLETION 16 /* MAX iterations before aborting I2C */
+
+/*** OCI Bus access **********************************************************/
+
+static int oci_write(struct pore_bus *b, uint64_t addr,
+ const uint8_t *buf, unsigned int len,
+ int *err_code)
+{
+ struct pore_bus *oci = b->slaves[0];
+
+ if (!oci) {
+ eprintf(b->pore, "err: no oci available!\n");
+ return PORE_ERR_NOACK;
+ }
+
+ bprintf(b->pore, " %-12s: %s(%p, 0x%llx, %p, %x)\n", b->name,
+ __func__, b, (long long)addr, buf, len);
+ return poreb_write(oci, addr & PORE_BITS_32_63, buf, len, err_code);
+}
+
+static int oci_read(struct pore_bus *b, uint64_t addr, uint8_t *buf,
+ unsigned int len, int *err_code)
+{
+ struct pore_bus *oci = b->slaves[0];
+
+ if (!oci) {
+ eprintf(b->pore, "err: no oci available!\n");
+ return PORE_ERR_NOACK;
+ }
+
+ bprintf(b->pore, " %-12s: %s(%p, 0x%llx, %p, %x)\n", b->name,
+ __func__, b, (long long)addr, buf, len);
+ return poreb_read(oci, addr & PORE_BITS_32_63, buf, len, err_code);
+}
+
+/// Fetch Instruction Word from OCI Buffer
+///
+/// This method returns an instruction word from the fetch buffer. If
+/// the fetch buffer is empty, it does an OCI interface read and
+/// populates the buffer before returning the word.
+
+static int fetchInstructionWordOci(struct pore_bus *b, PoreAddress *pc,
+ uint32_t *word, int *err_code)
+{
+ int me = 0;
+ uint32_t offset = pc->offset;
+ pore_model_t p = b->pore;
+ struct pore_bus *oci = b->slaves[0];
+
+ // If the fetch buffer is not valid, or the data is not
+ // already present it is fetched. Then the correct word is
+ // returned from the buffer.
+
+ if(!p->oci_fetchBufferValid ||
+ (p->oci_fetchBufferCursor != (offset & 0xfffffff8))) {
+
+ p->oci_fetchBufferCursor = offset & 0xfffffff8;
+ me = poreb_read(oci, p->oci_fetchBufferCursor,
+ (uint8_t *)&p->oci_fetchBuffer,
+ sizeof(p->oci_fetchBuffer), err_code);
+ if (me < 0)
+ return PORE_ERR_FETCH;
+
+ p->oci_fetchBufferValid = 1;
+ }
+ *word = ((offset & 0x7) == 0) ?
+ p->oci_fetchBuffer >> 32 :
+ p->oci_fetchBuffer & 0xffffffff;
+
+ return me;
+}
+
+/// Model the 1 or 3 word instruction fetch from OCI.
+///
+/// This is for GPE0/1 and SLW, and goes through the OCI 8-byte instruction
+/// buffer.
+static int oci_fetch(struct pore_bus *b, uint64_t _pc,
+ uint64_t *ibuf_01, uint64_t *ibuf_2,
+ unsigned int *size, int *err_code)
+{
+ int me;
+ uint32_t i_word;
+ PoreAddress pc;
+ pore_model_t p = b->pore;
+
+ if (!b || !ibuf_01 || !ibuf_2 || !size || !err_code)
+ return PORE_ERR_INVALID_PARAM;
+
+ pc.val = _pc;
+ *ibuf_01 = *ibuf_2 = 0;
+ pore_relocateAddress(p, &pc.val);
+
+ me = fetchInstructionWordOci(b, &pc, &i_word, err_code);
+ if (me < 0)
+ return PORE_ERR_FETCH;
+ *ibuf_01 = (uint64_t)i_word << 32;
+ *size = 4;
+
+ if (i_word & 0x80000000) {
+ pc.offset += 4;
+ me = fetchInstructionWordOci(b, &pc, &i_word, err_code);
+ if (me < 0)
+ return PORE_ERR_FETCH;
+ *size += 4;
+ *ibuf_01 |= i_word;
+ pc.offset += 4;
+ me = fetchInstructionWordOci(b, &pc, &i_word, err_code);
+ if (me < 0)
+ return PORE_ERR_FETCH;
+ *size += 4;
+ *ibuf_2 = (uint64_t)i_word << 32;
+ }
+ return me;
+}
+
+static int oci_reset(pore_bus_t b)
+{
+ pore_model_t p = b->pore;
+
+ p->oci_fetchBufferValid = 0;
+ p->oci_fetchBufferCursor = 0;
+ p->oci_fetchBuffer = 0;
+ return 0;
+}
+
+struct pore_bus *poreb_create_pore2oci(struct pore_model *p,
+ const char *name,
+ struct pore_bus *oci)
+{
+ struct pore_bus *b;
+
+ if (!p) {
+ BUG();
+ return NULL;
+ }
+
+ b = poreb_create(name, 0, oci_read, oci_write,
+ oci_fetch, oci_reset);
+ if (!b)
+ return NULL;
+
+ p->oci_fetchBufferValid = 0;
+ p->oci_fetchBufferCursor = 0;
+ p->oci_fetchBuffer = 0;
+ b->slaves[0] = oci;
+ b->pore = p;
+
+ return b;
+}
+
+/*** Virtual bus to represent the address range for an fi2c master ***********/
+
+struct pore_fi2cm {
+ struct pore_bus *pib;
+ pore_i2c_en_param_reg *i2c_param; /* reference to pore_model */
+};
+
+/**
+ * Convert a PoreAddress + I2C register offset into a PIB address
+ */
+static uint32_t
+i2cPibAddress(PoreAddress *address, uint16_t offset)
+{
+ return ((address->memorySpace & 0x3fff) << 16) + offset;
+}
+
+static int fi2cm_setAddress(struct pore_bus *b, uint64_t addr, int *err_code)
+{
+ int rc;
+ unsigned int count;
+ pore_model_t p = b->pore;
+ struct pore_fi2cm *fi2cm = (struct pore_fi2cm *)poreb_get_priv(b);
+ pore_i2c_en_param_reg *i2cp = fi2cm->i2c_param;
+ PoreAddress address;
+ fasti2c_control_reg control;
+ fasti2c_status_reg status;
+ uint32_t pib_addr;
+
+ iprintf(p, "############ I2C SET ADDRESS #########################\n");
+
+ /* 4.7.3.1 Set Address */
+ address.val = addr;
+
+ /* 1. Write fast I2C Control Register at PRV address */
+ control.val = 0;
+ control.with_start = 1;
+ control.with_address = 1;
+ control.with_stop = 1;
+ control.read_continue = 0;
+ control.data_length = 0; /* mark this as address write */
+ control.device_address = i2cp->i2c_engine_device_id;
+ control.read_not_write = 0; /* address write */
+ control.speed = i2cp->i2c_engine_speed;
+ control.port_number = i2cp->i2c_engine_port;
+ control.address_range = i2cp->i2c_engine_address_range;
+
+ /* Add required address bytes to control register */
+ control.val |= (address.offset <<
+ ((4 - i2cp->i2c_engine_address_range)*8));
+
+ pib_addr = i2cPibAddress(&address, FASTI2C_CONTROL_OFFSET);
+ rc = pore_pib_write(p, pib_addr, (uint8_t *)&control.val,
+ sizeof(control.val), err_code);
+ if (rc < 0)
+ return rc;
+
+ /* 2. Wait for Data fill-level is 4/8 Bytes by polling fast
+ * I2C status register at PRV address
+ */
+ pib_addr = i2cPibAddress(&address, FASTI2C_STATUS_OFFSET);
+ for (count = 0; count < I2C_COMMAND_COMPLETION; count++) {
+
+ rc = pore_pib_read(p, pib_addr, (uint8_t *)&status.val,
+ sizeof(status.val), err_code);
+ if (rc != sizeof(status.val))
+ break;
+
+ iprintf(p, "I2C_COMMAND_STATUS=%016llx count=%d\n"
+ " i2c_command_complete = %x\n"
+ " i2c_fifo_entry_count = %x\n",
+ (long long)status.val, count,
+ (unsigned int)status.i2c_command_complete,
+ (unsigned int)status.i2c_fifo_entry_count);
+
+ if (status.i2c_command_complete)
+ break;
+ }
+ /* Check for timeout or error */
+ if (count == I2C_COMMAND_COMPLETION || (rc < 0))
+ return pore_handleErrEvent(p, 1, PORE_ERR_I2C_POLLING);
+
+ return rc;
+}
+
+static int fi2cm_read(struct pore_bus *b, uint64_t addr, uint8_t *buf,
+ unsigned int size, int *err_code)
+{
+ int rc;
+ unsigned int count;
+ pore_model_t p = b->pore;
+ struct pore_fi2cm *fi2cm = (struct pore_fi2cm *)poreb_get_priv(b);
+ pore_i2c_en_param_reg *i2cp = fi2cm->i2c_param;
+ PoreAddress address;
+ fasti2c_control_reg control;
+ fasti2c_status_reg status;
+ uint32_t pib_addr;
+ uint64_t read_data = 0;
+
+ if (((size != 8) && (size != 4)) ||
+ ((i2cp->i2c_engine_address_range != 2) &&
+ (i2cp->i2c_engine_address_range != 4)))
+ return PORE_ERR_INVALID_PARAM;
+
+ rc = fi2cm_setAddress(b, addr, err_code);
+ if (rc < 0)
+ return rc;
+
+ iprintf(p, "############ I2C READ (len=%d) #######################\n",
+ size);
+
+ /* 4.7.3.2 Get Data (4 byte or 8 byte) */
+ address.val = addr;
+
+ /* 1. Write fast I2C Control Register at PRV address */
+ control.val = 0;
+ control.with_start = 1;
+ control.with_address = 1;
+ control.with_stop = 1;
+ control.read_continue = 0;
+ control.data_length = size;
+ control.device_address = i2cp->i2c_engine_device_id;
+ control.read_not_write = 1; /* read */
+ control.speed = i2cp->i2c_engine_speed;
+ control.port_number = i2cp->i2c_engine_port;
+ control.address_range = i2cp->i2c_engine_address_range;
+
+ /* Add required address bytes to control register */
+ control.val |= (address.offset <<
+ ((4 - i2cp->i2c_engine_address_range)*8));
+
+ pib_addr = i2cPibAddress(&address, FASTI2C_CONTROL_OFFSET);
+ rc = pore_pib_write(p, pib_addr, (uint8_t *)&control.val,
+ sizeof(control.val), err_code);
+ if (rc < 0)
+ return rc;
+
+ /* 2. Wait for Data fill-level is 4/8 Bytes by polling fast
+ * I2C status register at PRV address
+ */
+ pib_addr = i2cPibAddress(&address, FASTI2C_STATUS_OFFSET);
+ for (count = 0; count < I2C_COMMAND_COMPLETION; count++) {
+
+ rc = pore_pib_read(p, pib_addr, (uint8_t *)&status.val,
+ sizeof(status.val), err_code);
+ if (rc != sizeof(status.val))
+ break;
+
+ iprintf(p, "I2C_COMMAND_STATUS=%016llx count=%d\n"
+ " i2c_command_complete = %x\n"
+ " i2c_fifo_entry_count = %x\n",
+ (long long)status.val, count,
+ (unsigned int)status.i2c_command_complete,
+ (unsigned int)status.i2c_fifo_entry_count);
+
+ if ((status.i2c_command_complete) &&
+ (status.i2c_fifo_entry_count == size)) {
+ break;
+ }
+ }
+ /* Check for timeout or error */
+ if (count == I2C_COMMAND_COMPLETION || (rc < 0))
+ return pore_handleErrEvent(p, 1, PORE_ERR_I2C_POLLING);
+
+ /* 3. Read 32 or 64 bit from fast I2C data register at PRV address */
+ pib_addr = i2cPibAddress(&address, FASTI2C_DATA_OFFSET);
+ rc = pore_pib_read(p, pib_addr, (uint8_t *)&read_data,
+ sizeof(read_data), err_code);
+ read_data >>= (8 - size) * 8;
+
+ /* Thi N Trans proposal
+ *
+ * #if (__BYTE_ORDER == __LITTLE_ENDIAN)
+ * memcpy(buf, (uint8_t *)&read_data, size);
+ * #else
+ * memcpy(buf, (uint8_t *)&read_data + (8 - size), size);
+ * #endif
+ */
+
+ switch (size) {
+ case 4: *(uint32_t *)buf = read_data; break;
+ case 8: *(uint64_t *)buf = read_data; break;
+ }
+ return size;
+}
+
+/**
+ * I2C Write
+ * o Fill control register with required data. If i2c_engine_address_range
+ * allows, we need to fill the first few bytes into the control register.
+ * o Write the data register with the remaining bytes.
+ * o Poll for completion of the operation.
+ */
+static int fi2cm_write(struct pore_bus *b, uint64_t addr,
+ const uint8_t *buf, unsigned int size,
+ int *err_code)
+{
+ int rc, count;
+ pore_model_t p = b->pore;
+ struct pore_fi2cm *fi2cm = (struct pore_fi2cm *)poreb_get_priv(b);
+ pore_i2c_en_param_reg *i2cp = fi2cm->i2c_param;
+ fasti2c_control_reg control;
+ fasti2c_status_reg status;
+ PoreAddress address;
+ uint32_t pib_addr;
+ uint64_t write_data;
+
+ if ((size != 8) ||
+ ((i2cp->i2c_engine_address_range != 2) &&
+ (i2cp->i2c_engine_address_range != 4)))
+ return PORE_ERR_INVALID_PARAM;
+
+ rc = fi2cm_setAddress(b, addr, err_code);
+ if (rc < 0)
+ return rc;
+
+ iprintf(p, "############ I2C WRITE ###############################\n");
+
+ /* 4.7.3.3 Write Data (8 byte, SBE memory interface only) */
+ address.val = addr;
+ write_data = *((uint64_t *)buf);
+
+ /* 1. Write fast I2C Control Register at PRV address */
+ control.val = 0;
+ control.with_start = 1;
+ control.with_address = 1;
+ control.with_stop = 1;
+ control.read_continue = 0;
+ control.data_length = size;
+ control.device_address = i2cp->i2c_engine_device_id;
+ control.read_not_write = 0; /* write */
+ control.speed = i2cp->i2c_engine_speed;
+ control.port_number = i2cp->i2c_engine_port;
+ control.address_range = i2cp->i2c_engine_address_range;
+
+ /* Add required address bytes to control register */
+ control.val |= (address.offset <<
+ ((4 - i2cp->i2c_engine_address_range)*8));
+
+ /* Add possible data bytes to control register */
+ if (i2cp->i2c_engine_address_range < 4)
+ control.val |= (write_data >>
+ (64 - ((4-i2cp->i2c_engine_address_range)*8)));
+
+ pib_addr = i2cPibAddress(&address, FASTI2C_CONTROL_OFFSET);
+ rc = pore_pib_write(p, pib_addr, (uint8_t *)&control.val,
+ sizeof(control.val), err_code);
+ if (rc < 0)
+ return rc;
+
+ /* 2. Write fast I2C Data Register at PRV address */
+
+ /* Write remaining data bytes to data register (left algined)*/
+ write_data = write_data << ((4 - i2cp->i2c_engine_address_range) * 8);
+
+ pib_addr = i2cPibAddress(&address, FASTI2C_DATA_OFFSET);
+ rc = pore_pib_write(p, pib_addr, (uint8_t *)&write_data,
+ sizeof(write_data), err_code);
+ if (rc < 0)
+ return rc;
+
+ /**
+ * 3. Wait and poll fast I2C status register for operation to
+ * complete at PRV address
+ */
+ /* FIXME Check instead bit 44 (which is not right in my
+ * register definition!
+ */
+ pib_addr = i2cPibAddress(&address, FASTI2C_STATUS_OFFSET);
+ for (count = 0; count < I2C_COMMAND_COMPLETION; count++) {
+
+ rc = pore_pib_read(p, pib_addr, (uint8_t *)&status.val,
+ sizeof(status.val), err_code);
+ if (rc != sizeof(status.val))
+ break;
+
+ iprintf(p, "I2C_COMMAND_STATUS=%016llx count=%d\n"
+ " i2c_command_complete = %x\n"
+ " i2c_fifo_entry_count = %x\n",
+ (long long)status.val, count,
+ (unsigned int)status.i2c_command_complete,
+ (unsigned int)status.i2c_fifo_entry_count);
+
+ if (status.i2c_command_complete) {
+ return size;
+ }
+ }
+ return pore_handleErrEvent(p, 1, PORE_ERR_I2C_POLLING);
+}
+
+struct pore_bus *poreb_create_fi2cm(pore_model_t p, const char *name,
+ pore_bus_t pib,
+ pore_i2c_en_param_reg *i2c_param)
+{
+ struct pore_bus *b;
+ struct pore_fi2cm *e;
+
+ b = poreb_create(name, sizeof(*e), fi2cm_read, fi2cm_write,
+ NULL, NULL);
+ if (!b)
+ return NULL;
+
+ e = (struct pore_fi2cm *)poreb_get_priv(b);
+ e->i2c_param = i2c_param;
+ e->pib = pib;
+ b->pore = p;
+
+ return b;
+}
+
+/* FIXME
+ * 1. Select fi2c master using memory_reloc and oci_base register.
+ * 2. Perform fi2c access.
+ */
+static int fi2c_read(struct pore_bus *b, uint64_t addr, uint8_t *buf,
+ unsigned int len, int *err_code)
+{
+ int i;
+ uint32_t port;
+ pore_model_t p = b->pore;
+ PoreAddress address;
+
+ bprintf(p, " %-12s: %s(%p, 0x%llx, %p, %x)\n", b->name, __func__, b,
+ (long long)addr, buf, len);
+
+ address.val = addr;
+ port = address.memorySpace & 0xf; /* must match i2c_engine_id */
+
+ for (i = 0; i < 3; i++) {
+ struct pore_bus *fi2cm = b->slaves[i];
+
+ if (!fi2cm)
+ continue;
+ if (!fi2cm->read)
+ continue;
+
+ /* Is this fi2c master target of the desired transfer?
+ * Check i2c_engine_identifier against the port number
+ * encoded in the upper parts of he address we got.
+ * The upper part is contructed using the OCI_base register
+ * used for this acess.
+ */
+ if (p->i2c_e_param[i].i2c_engine_identifier != port) {
+ continue;
+ }
+
+ return poreb_read(fi2cm, addr, buf, len, err_code);
+ }
+
+ return PORE_ERR_READ;
+}
+
+static int fi2c_write(struct pore_bus *b, uint64_t addr,
+ const uint8_t *buf, unsigned int len,
+ int *err_code)
+{
+ int i;
+ uint32_t port;
+ pore_model_t p = b->pore;
+ PoreAddress address;
+
+ address.val = addr;
+ port = address.memorySpace & 0xf; /* must match i2c_engine_id */
+
+ for (i = 0; i < 3; i++) {
+ struct pore_bus *fi2cm = b->slaves[i];
+
+ if (!fi2cm)
+ continue;
+ if (!fi2cm->write)
+ continue;
+
+ /* is this fi2c master target of the desired transfer?
+ * I originally wanted to do this compare in the fi2cm
+ * code but that did not work with memory emulation
+ * which is not aware of the condition below.
+ */
+ if (p->i2c_e_param[i].i2c_engine_identifier != port) {
+ continue;
+ }
+
+ return poreb_write(fi2cm, addr, buf, len, err_code);
+
+ }
+
+ return PORE_ERR_WRITE;
+}
+
+/// Model 1 or 3 word instruction fetch using indirect PIB addressing (SBE).
+static int fi2c_fetch(struct pore_bus *b, uint64_t _pc,
+ uint64_t *ibuf_01, uint64_t *ibuf_2,
+ unsigned int *size, int *err_code)
+{
+ int me = PORE_SUCCESS;
+ uint32_t i_word;
+ PoreAddress pc;
+ pore_model_t p = b->pore;
+
+ if (!b || !ibuf_01 || !ibuf_2 || !size || !err_code)
+ return PORE_ERR_INVALID_PARAM;
+
+ *size = 0;
+ *ibuf_01 = *ibuf_2 = 0;
+ pc.val = _pc;
+ pore_relocateAddress(p, &pc.val);
+
+ me = fi2c_read(b, pc.val, (uint8_t *)&i_word,
+ sizeof(i_word), err_code);
+ if (me != sizeof(i_word))
+ return PORE_ERR_FETCH;
+
+ *ibuf_01 = (uint64_t)i_word << 32;
+ *size = 4;
+
+ if (i_word & 0x80000000) {
+ pc.offset += 4;
+ me = fi2c_read(b, pc.val, (uint8_t *)&i_word,
+ sizeof(i_word), err_code);
+ if (me != sizeof(i_word))
+ return PORE_ERR_FETCH;
+ *size += 4;
+ *ibuf_01 |= i_word;
+ pc.offset += 4;
+ me = fi2c_read(b, pc.val, (uint8_t *)&i_word,
+ sizeof(i_word), err_code);
+ if (me != sizeof(i_word))
+ return PORE_ERR_FETCH;
+ *size += 4;
+ *ibuf_2 = (uint64_t)i_word << 32;
+ }
+ return me;
+}
+
+
+struct pore_bus *poreb_create_pore2fi2c(pore_model_t p,
+ const char *name,
+ struct pore_bus *fi2c0,
+ struct pore_bus *fi2c1,
+ struct pore_bus *fi2c2)
+{
+ struct pore_bus *b;
+
+ b = poreb_create(name, 0, fi2c_read, fi2c_write, fi2c_fetch, NULL);
+ if (!b)
+ return NULL;
+
+ b->slaves[0] = fi2c0;
+ b->slaves[1] = fi2c1;
+ b->slaves[2] = fi2c2;
+ b->pore = p;
+
+ return b;
+}
+
+/*** PIB slave to implement self-scomming functionality **********************/
+
+static int selfscom_read(struct pore_bus *b, uint64_t addr,
+ uint8_t *buf, unsigned int len,
+ int *err_code)
+{
+ uint64_t *val64 = (uint64_t *)buf;
+ PibAddress pib_addr, *pore_addr = (PibAddress *)poreb_get_priv(b);
+
+ pib_addr.val = addr;
+ if ((pib_addr.chiplet_id != pore_addr->chiplet_id) ||
+ (pib_addr.prv_port != pore_addr->prv_port))
+ return PORE_ERR_NOACK;
+
+ if (!b->pore)
+ return PORE_ERR_NOACK;
+
+ switch (addr & 0xffff) {
+ /* vPORe register - self-scomming */
+ case PORE_R_STATUS:
+ case PORE_R_CONTROL:
+ case PORE_R_RESET:
+ case PORE_R_ERROR_MASK:
+ case PORE_R_PRV_BASE_ADDR0:
+ case PORE_R_PRV_BASE_ADDR1:
+ case PORE_R_OCI_MEMORY_BASE_ADDR0:
+ case PORE_R_OCI_MEMORY_BASE_ADDR1:
+ case PORE_R_TABLE_BASE_ADDR:
+ case PORE_R_EXE_TRIGGER:
+ case PORE_R_SCRATCH0:
+ case PORE_R_SCRATCH1:
+ case PORE_R_SCRATCH2:
+ case PORE_R_IBUF_01:
+ case PORE_R_IBUF_2:
+ case PORE_R_DBG0:
+ case PORE_R_DBG1:
+ case PORE_R_PC_STACK0:
+ case PORE_R_PC_STACK1:
+ case PORE_R_PC_STACK2:
+ case PORE_R_ID_FLAGS:
+ case PORE_R_DATA0:
+ case PORE_R_MEM_RELOC:
+ case PORE_R_I2C_E0_PARAM:
+ case PORE_R_I2C_E1_PARAM:
+ case PORE_R_I2C_E2_PARAM:
+ *val64 = pore_readReg(b->pore, (pore_reg_t)(addr & 0xff),
+ PORE_BITS_0_63);
+ *err_code = PORE_PCB_SUCCESS;
+ return len;
+ }
+
+ return PORE_ERR_NOACK;
+}
+
+static int selfscom_write(struct pore_bus *b, uint64_t addr,
+ const uint8_t *buf, unsigned int len,
+ int *err_code)
+{
+ uint64_t *val64 = (uint64_t *)buf;
+ PibAddress pib_addr, *pore_addr = (PibAddress *)poreb_get_priv(b);
+
+ pib_addr.val = addr;
+ if ((pib_addr.chiplet_id != pore_addr->chiplet_id) ||
+ (pib_addr.prv_port != pore_addr->prv_port))
+ return PORE_ERR_NOACK;
+
+ if (!b->pore)
+ return PORE_ERR_NOACK;
+
+ switch (addr & 0xffff) {
+ /* vPORe register - self-scomming */
+ case PORE_R_STATUS:
+ case PORE_R_CONTROL:
+ case PORE_R_RESET:
+ case PORE_R_ERROR_MASK:
+ case PORE_R_PRV_BASE_ADDR0:
+ case PORE_R_PRV_BASE_ADDR1:
+ case PORE_R_OCI_MEMORY_BASE_ADDR0:
+ case PORE_R_OCI_MEMORY_BASE_ADDR1:
+ case PORE_R_TABLE_BASE_ADDR:
+ case PORE_R_EXE_TRIGGER:
+ case PORE_R_SCRATCH0:
+ case PORE_R_SCRATCH1:
+ case PORE_R_SCRATCH2:
+ case PORE_R_IBUF_01:
+ case PORE_R_IBUF_2:
+ case PORE_R_DBG0:
+ case PORE_R_DBG1:
+ case PORE_R_PC_STACK0:
+ case PORE_R_PC_STACK1:
+ case PORE_R_PC_STACK2:
+ case PORE_R_ID_FLAGS:
+ case PORE_R_DATA0:
+ case PORE_R_MEM_RELOC:
+ case PORE_R_I2C_E0_PARAM:
+ case PORE_R_I2C_E1_PARAM:
+ case PORE_R_I2C_E2_PARAM:
+ pore_writeReg(b->pore, (pore_reg_t)(addr & 0xff),
+ *val64, PORE_BITS_0_63);
+ *err_code = PORE_PCB_SUCCESS;
+ return len;
+ }
+
+ return PORE_ERR_NOACK;
+}
+
+struct pore_bus *poreb_create_selfscom(const char *name,
+ unsigned int chiplet_id,
+ unsigned int prv_port)
+{
+ struct pore_bus *b;
+ PibAddress *pib_addr;
+
+ b = poreb_create(name, sizeof(*pib_addr), selfscom_read,
+ selfscom_write, NULL, NULL);
+ if (!b)
+ return NULL;
+ pib_addr = (PibAddress *)poreb_get_priv(b);
+ pib_addr->val = 0;
+ pib_addr->chiplet_id = chiplet_id;
+ pib_addr->prv_port = prv_port;
+
+ return b;
+}
+
+/*** Generic Bus functionality ***********************************************/
+
+static int __poreb_read(struct pore_bus *b, uint64_t addr,
+ uint8_t *buf, unsigned int len,
+ int *err_code)
+{
+ int last_rc = PORE_ERR_NOACK, good_rcs = 0, rc = 0;
+ unsigned int i;
+
+ for (i = 0; i < PORE_MAX_BUS; i++) {
+ struct pore_bus *s = b->slaves[i];
+
+ if (s == NULL)
+ continue;
+
+ /* We expect PORE_ERR_NOACK if slave is ok, but not
+ * responsible for this transfer. If anything else is
+ * returned the first one has it, else try another
+ * slave.
+ */
+ rc = poreb_read(s, addr, buf, len, err_code);
+ if (rc != PORE_ERR_NOACK) {
+ last_rc = rc;
+ good_rcs++;
+
+ return last_rc; /* FIXME Do not return!!! */
+ }
+ }
+ if (good_rcs > 1) {
+ BUG();
+ return PORE_ERR_BUS_COLLISION;
+ }
+
+ return last_rc;
+}
+
+
+static int __poreb_write(struct pore_bus *b, uint64_t addr,
+ const uint8_t *buf, unsigned int len,
+ int *err_code)
+{
+ int last_rc = PORE_ERR_NOACK, good_rcs = 0, rc = 0;
+ unsigned int i;
+
+ for (i = 0; i < PORE_MAX_BUS; i++) {
+ struct pore_bus *s = b->slaves[i];
+
+ if (s == NULL)
+ continue;
+
+ /* We expect PORE_ERR_NOACK if slave is ok, but not
+ * responsible for this transfer. If anything else is
+ * returned the first one has it, else try another
+ * slave.
+ */
+ rc = poreb_write(s, addr, buf, len, err_code);
+ if (rc != PORE_ERR_NOACK) {
+ last_rc = rc;
+ good_rcs++;
+
+ return last_rc; /* FIXME Do not return!!! */
+ }
+ }
+ if (good_rcs > 1) {
+ BUG();
+ return PORE_ERR_BUS_COLLISION;
+ }
+
+ return last_rc;
+}
+
+void poreb_destroy(pore_bus_t b)
+{
+ unsigned int i;
+
+ if (!b) return;
+ for (i = 0; i < PORE_MAX_BUS; i++) {
+ if (b->slaves[i])
+ poreb_destroy(b->slaves[i]);
+ }
+ free(b);
+}
+
+struct pore_bus *
+poreb_create(const char *name, size_t priv_data_size,
+ poreb_read_f r, poreb_write_f w,
+ poreb_fetch_f f, poreb_reset_f R)
+{
+ struct pore_bus *b;
+
+ b = (struct pore_bus *)malloc(sizeof(*b) + priv_data_size);
+ if (!b)
+ return NULL;
+ memset(b, 0, sizeof(*b) + priv_data_size);
+
+ b->name = name;
+ b->read = (r) ? (r) : (__poreb_read);
+ b->write = (w) ? (w) : (__poreb_write);
+ b->fetch = (f) ? (f) : (NULL);
+ b->reset = (R) ? (R) : (NULL);
+
+ return b;
+}
+
+int poreb_read(pore_bus_t b, uint64_t addr, uint8_t *buf,
+ unsigned int size, int *err_code)
+{
+ if (!b)
+ return PORE_ERR_INVALID_PARAM;
+ if (!b->read)
+ return PORE_ERR_NOT_IMPLEMENTED;
+ return b->read(b, addr, buf, size, err_code);
+}
+
+int poreb_write(pore_bus_t b, uint64_t addr, const uint8_t *buf,
+ unsigned int size, int *err_code)
+{
+ if (!b)
+ return PORE_ERR_INVALID_PARAM;
+ if (!b->write)
+ return PORE_ERR_NOT_IMPLEMENTED;
+ return b->write(b, addr, buf, size, err_code);
+}
+
+int poreb_fetch(pore_bus_t b, uint64_t pc, uint64_t *i_buf01,
+ uint64_t *i_buf2, unsigned int *size, int *err_code)
+{
+ if (!b)
+ return PORE_ERR_INVALID_PARAM;
+ if (!b->fetch)
+ return PORE_ERR_NOT_IMPLEMENTED;
+ return b->fetch(b, pc, i_buf01, i_buf2, size, err_code);
+}
+
+int poreb_reset(pore_bus_t p)
+{
+ if (!p)
+ return PORE_ERR_INVALID_PARAM;
+ if (!p->reset)
+ return PORE_ERR_NOT_IMPLEMENTED;
+ return p->reset(p);
+}
+
+int poreb_attach_slave(struct pore_bus *b, struct pore_bus *s)
+{
+ unsigned int i;
+
+ for (i = 0; i < PORE_MAX_BUS; i++) {
+ if (!b->slaves[i]) {
+ b->slaves[i] = s;
+ return 0;
+ }
+ }
+ return PORE_ERR_NOSPACE;
+}
diff --git a/src/usr/pore/poreve/pore_model/ibuf/pore_fi2c.c b/src/usr/pore/poreve/pore_model/ibuf/pore_fi2c.c
new file mode 100644
index 000000000..943751d86
--- /dev/null
+++ b/src/usr/pore/poreve/pore_model/ibuf/pore_fi2c.c
@@ -0,0 +1,550 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/pore_model/ibuf/pore_fi2c.c $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+/******************************************************************************
+ *
+ * Virtual PORe Engine
+ *
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pore_model.h"
+#include "pore_ibuf.h"
+#include "pore_regs.h"
+
+/// \enum FastI2cState
+///
+/// The state of the controller. Sequences of register operations are
+/// only allowed in a prescribed sequence, depending on the state of the
+/// controller. The ERROR state represents a bug in the model and is
+/// non-recoverable.
+
+typedef enum {
+ ERROR = 0,
+ IDLE = 1,
+ ADDRESS_WRITE_ONGOING = 2,
+ DATA_READ_ONGOING = 3,
+ DATA_AVAILABLE = 4,
+ WRITE_DATA_EXPECTED = 5,
+ DATA_WRITE_ONGOING = 6
+} FastI2cState;
+
+#define COMMAND_COMPLETION 3 /* command completion timeout */
+
+struct fi2c {
+ pore_bus_t bus;
+
+ uint8_t *mem_buf; /* memory used to emulate data access */
+ unsigned int mem_size; /* maximum size of attached memory */
+ unsigned int mem_start; /* memory start offset in address space */
+ unsigned int address; /* read/write offset */
+ uint64_t i2c_en_param_reg; /* figure out if transfer was for us */
+
+ unsigned int prv_port; /* pervasive port number */
+ size_t addressBytes; /* address bytes used, must match request */
+
+ unsigned int i2c_port; /* i2c port; a master can support multiple */
+ unsigned int deviceAddress; /* One FI2C can serve multiple
+ i2c_port/deviceAddress
+ combinations aka memory
+ areas. Support only one for
+ now. */
+ unsigned int command_completion;
+
+ FastI2cState state;
+ fasti2c_control_reg control;
+ fasti2c_status_reg status;
+ uint64_t fifo; /* Data is left-justified in this reg. */
+};
+
+/* Memory Access */
+
+static int mem_addressWrite(struct fi2c *p, size_t i_bytes, uint32_t i_address)
+{
+ if (i_bytes != p->addressBytes) {
+ BUG();
+ p->state = ERROR;
+ return PORE_ERR_I2CMEMORY_ILLEGAL_ADDR;
+ }
+ p->address = i_address;
+ return i_bytes;
+}
+
+/**
+ * We keep everything outside the PORe model big endian and turn it
+ * into host-byteorder when reading it in or vice versa when writing
+ * it out.
+ */
+static int mem_dataRead(struct fi2c *p, size_t i_bytes, uint64_t *o_data)
+{
+ unsigned int mem_offs = p->address - p->mem_start;
+
+ if ((p->address < p->mem_start) ||
+ (mem_offs + i_bytes > p->mem_size)) {
+ BUG();
+ p->state = ERROR;
+ return PORE_ERR_I2CMEMORY_ILLEGAL_ADDR;
+ }
+
+ switch (i_bytes) {
+ case 4:
+ *o_data = pore_be32toh(*((uint32_t *)&p->mem_buf[mem_offs]));
+ break;
+ case 8:
+ *o_data = pore_be64toh(*((uint64_t *)&p->mem_buf[mem_offs]));
+ break;
+ default:
+ return PORE_ERR_INVALID_PARAM;
+ }
+
+ p->address += i_bytes;
+ return i_bytes;
+}
+
+
+static int mem_dataWrite(struct fi2c *p, size_t i_bytes, uint64_t i_data)
+{
+ unsigned int mem_offs = p->address - p->mem_start;
+
+ if ((p->address < p->mem_start) ||
+ (mem_offs + i_bytes > p->mem_size)) {
+ BUG();
+ p->state = ERROR;
+ return PORE_ERR_I2CMEMORY_ILLEGAL_ADDR;
+ }
+
+ switch (i_bytes) {
+ case 4:
+ *((uint32_t *)&p->mem_buf[mem_offs]) = pore_htobe32(i_data);
+ break;
+ case 8:
+ *((uint64_t *)&p->mem_buf[mem_offs]) = pore_htobe64(i_data);
+ break;
+ default:
+ return PORE_ERR_INVALID_PARAM;
+ }
+
+ p->address += i_bytes;
+ return i_bytes;
+}
+
+static uint32_t getI2cAddress(fasti2c_control_reg *control)
+{
+ size_t addressBytes = control->address_range;
+ return (control->val & 0xffffffff) >> ((4 - addressBytes) * 8);
+}
+
+// The address is left-justified in the low-order 32 bits of the control
+// register.
+
+static int addressWrite(struct fi2c *p)
+{
+ int me;
+ unsigned i2c_port = p->control.port_number;
+ unsigned deviceAddress = p->control.device_address;
+ size_t addressBytes = p->control.address_range;
+
+ if ((p->i2c_port != i2c_port) || (p->deviceAddress != deviceAddress)) {
+ BUG();
+ return PORE_ERR_NOT_MAPPED_ON_FASTI2C;
+ }
+
+ me = mem_addressWrite(p, addressBytes, getI2cAddress(&p->control));
+ p->state = ADDRESS_WRITE_ONGOING;
+ return me;
+}
+
+
+static int dataRead(struct fi2c *p)
+{
+ int me;
+ unsigned i2c_port = p->control.port_number;
+ unsigned deviceAddress = p->control.device_address;
+ size_t dataBytes = p->control.data_length;
+ uint64_t data = 0;
+
+ if ((p->i2c_port != i2c_port) || (p->deviceAddress != deviceAddress)) {
+ BUG();
+ return PORE_ERR_NOT_MAPPED_ON_FASTI2C;
+ }
+
+ me = mem_dataRead(p, dataBytes, &data);
+ p->fifo = data << (64 - (dataBytes * 8));
+ p->state = DATA_READ_ONGOING;
+ return me;
+}
+
+// For addresses < 4 bytes, the first slug of data occupies the
+// remainder of the low-order word of the control register. Any
+// remaining bytes come in on the next transaction targeting the data
+// register. This code assumes 8-byte only data writes.
+
+static int initialDataWrite(struct fi2c *p)
+{
+ unsigned addressBytes = p->control.address_range;
+
+ if (addressBytes < 4) {
+ p->fifo = BE64_GET_FIELD(p->control.val & 0xffffffff,
+ 32 + (addressBytes * 8), 63)
+ << (64 - (4 - addressBytes) * 8);
+ }
+ p->state = WRITE_DATA_EXPECTED;
+ return PORE_SUCCESS;
+}
+
+// Assume 8-byte only write transactions
+
+static int finalDataWrite(struct fi2c *p, const uint8_t *buf, unsigned int len)
+{
+ int me;
+ unsigned i2c_port = p->control.port_number;
+ unsigned deviceAddress = p->control.device_address;
+ size_t addressBytes = p->control.address_range;
+ uint64_t i_data, i_merge;
+
+ if ((p->i2c_port != i2c_port) || (p->deviceAddress != deviceAddress)) {
+ BUG();
+ return PORE_ERR_NOT_MAPPED_ON_FASTI2C;
+ }
+ i_data = *(uint64_t *)buf;
+ i_merge = BE64_GET_FIELD(i_data, 0, (8 - addressBytes) * 8 - 1);
+ p->fifo = BE64_SET_FIELD(p->fifo, /* target */
+ addressBytes * 8, /* begin */
+ 63, /* end */
+ i_merge);
+
+ me = mem_dataWrite(p, len, p->fifo);
+ p->state = DATA_WRITE_ONGOING;
+ return me;
+}
+
+// Modeling notes:
+//
+// o The RESET register is not modeled here
+//
+// o Our models ignore the I2C Speed
+//
+// o Transactions complete in 0 time and polling always succeeds on the first
+// read of the status register. This is done to simplify the PORE
+// engine model.
+//
+// o Only the follwing types of control register actions are modeled:
+// * Address write : with_start; with_address; !with_continue; with_stop;
+// data_length == 0
+// * Data read : with_start; with_address; !with_continue; with_stop;
+// data_length == [4,8]
+// * Data write : with_start; with_address; !with_continue; with_stop;
+// data_length == 8
+//
+// o The memory models hold the last address written
+//
+// o Redundant reads of the STATUS register are allowed
+//
+// o PORE only does 4/8 byte reads and 8 byte writes, so any other data
+// access is considered an error (although the models could easily be
+// extended to allow them).
+
+static int fi2c_read(struct pore_bus *b, uint64_t addr,
+ uint8_t *buf, unsigned int len,
+ int *err_code)
+{
+ int rc = PORE_FAILURE;
+ PibAddress pib_addr;
+ struct fi2c *p = (struct fi2c *)poreb_get_priv(b);
+
+ iprintf(b->pore, " %-12s: %s(%p, 0x%llx, %p, %x)\n",
+ b->name, __func__, b, (long long)addr, buf, len);
+
+ /* SBE has: prv_port 0xa SEEPROM 2 byte addresses
+ * " 0x1 OTP 2 byte addresses
+ * " 0xb PNOR 4 byte addresses
+ *
+ * This is adjusted in the i2c_en_param_reg in the fields
+ * i2c_engine_identifier == prv_port and
+ * i2c_engine_address_range == addressBytes.
+ *
+ * All FI2CMs are in the pervasive chiplet which has 0x0.
+ */
+ pib_addr.val = addr;
+ if ((pib_addr.chiplet_id != 0x0) || (pib_addr.prv_port != p->prv_port))
+ return PORE_ERR_NOACK; /* not for this fi2cm */
+
+ switch (pib_addr.local_addr) {
+
+ case FASTI2C_CONTROL_OFFSET:
+ p->state = ERROR;
+ rc = PORE_ERR_WRITE_ONLY_REGISTER;
+ break;
+
+ case FASTI2C_STATUS_OFFSET:
+ if (len != 8) {
+ rc = PORE_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (p->state) {
+
+ case ADDRESS_WRITE_ONGOING:
+ case DATA_WRITE_ONGOING:
+ p->command_completion++; /* simulate access duration */
+ if (p->command_completion < COMMAND_COMPLETION) {
+ p->status.val = 0;
+ *(uint64_t *)buf = p->status.val;
+ rc = len;
+ break;
+ }
+
+ p->command_completion = 0;
+ p->status.val = 0;
+ p->status.i2c_command_complete = 1;
+ *(uint64_t *)buf = p->status.val;
+ p->state = IDLE;
+ rc = len;
+ break;
+
+ case DATA_READ_ONGOING:
+
+ p->command_completion++; /* simulate access duration */
+ if (p->command_completion < COMMAND_COMPLETION) {
+ p->status.val = 0;
+ *(uint64_t *)buf = p->status.val;
+ rc = len;
+ break;
+ }
+
+ p->command_completion = 0;
+ p->status.val = 0;
+ p->status.i2c_command_complete = 1;
+ p->status.i2c_fifo_entry_count =
+ p->control.data_length;
+ *(uint64_t *)buf = p->status.val;
+ p->state = DATA_AVAILABLE;
+ rc = len;
+ break;
+
+ case IDLE:
+ *(uint64_t *)buf = p->status.val;
+ rc = len;
+ break;
+
+ default:
+ BUG();
+ p->state = ERROR;
+ rc = PORE_ERR_FASTI2C_SEQUENCE_ERROR;
+ break;
+ }
+ break;
+
+ case FASTI2C_DATA_OFFSET:
+ switch (p->state) {
+
+ case DATA_AVAILABLE:
+ rc = len;
+ switch (len) {
+ case 4: *(uint32_t *)buf = (uint32_t)p->fifo; break;
+ case 8: *(uint64_t *)buf = (uint64_t)p->fifo; break;
+ default:
+ rc = PORE_ERR_INVALID_PARAM;
+ break;
+ }
+ p->state = IDLE;
+ break;
+
+ default:
+ BUG();
+ p->state = ERROR;
+ rc = PORE_ERR_FASTI2C_SEQUENCE_ERROR;
+ break;
+ }
+ break;
+
+ default:
+ return PORE_ERR_NOACK; /* not for this fi2cm */
+ }
+
+ *err_code = PORE_PCB_SUCCESS;
+ return rc;
+}
+
+
+static int fi2c_write(struct pore_bus *b, uint64_t addr,
+ const uint8_t *buf, unsigned int len,
+ int *err_code)
+{
+ int rc = PORE_FAILURE;
+ PibAddress pib_addr;
+ struct fi2c *p = (struct fi2c *)poreb_get_priv(b);
+
+ iprintf(b->pore, " %-12s: %s(%p, 0x%llx, %p, %x)\n",
+ b->name, __func__, b, (long long)addr, buf, len);
+
+ /* SBE has: prv_port 0xa SEEPROM 2 byte addresses
+ * " 0x1 OTP 2 byte addresses
+ * " 0xb PNOR 4 byte addresses
+ *
+ * This is adjusted in the i2c_en_param_reg in the fields
+ * i2c_engine_identifier == prv_port and
+ * i2c_engine_address_range == addressBytes.
+ *
+ * All FI2CMs are in the pervasive chiplet which has 0x0.
+ */
+ pib_addr.val = addr;
+ if ((pib_addr.chiplet_id != 0x0) || (pib_addr.prv_port != p->prv_port))
+ return PORE_ERR_NOACK; /* not for this fi2cm */
+
+ switch (pib_addr.local_addr) {
+
+ case FASTI2C_CONTROL_OFFSET:
+ if (len != 8) {
+ rc = PORE_ERR_INVALID_PARAM;
+ break;
+ }
+ if (p->state != IDLE) {
+ BUG();
+ p->state = ERROR;
+ rc = PORE_ERR_FASTI2C_SEQUENCE_ERROR;
+ break;
+ }
+
+ p->control.val = *(uint64_t *)buf;
+
+ if (!p->control.with_start ||
+ !p->control.with_address ||
+ p->control.read_continue ||
+ !p->control.with_stop) {
+ BUG();
+ p->state = ERROR;
+ rc = PORE_ERR_FASTI2C_CONTROL_ERROR;
+ break;
+ }
+
+ if (p->control.read_not_write == 0) {
+ if (p->control.address_range == 0) {
+ BUG();
+ p->state = ERROR;
+ rc = PORE_ERR_FASTI2C_CONTROL_ERROR;
+ break;
+ }
+ if (p->control.data_length == 0) {
+ rc = addressWrite(p);
+ if (rc < 0)
+ break;
+ rc = len;
+ break;
+ }
+ if (p->control.data_length != 8) {
+ BUG();
+ p->state = ERROR;
+ rc = PORE_ERR_FASTI2C_CONTROL_ERROR;
+ break;
+ }
+ rc = initialDataWrite(p);
+ if (rc == PORE_SUCCESS)
+ rc = len;
+ break;
+
+ } else {
+ if ((p->control.data_length != 4) &&
+ (p->control.data_length != 8)) {
+ BUG();
+ p->state = ERROR;
+ rc = PORE_ERR_FASTI2C_CONTROL_ERROR;
+ break;
+ }
+ rc = dataRead(p);
+ break;
+ }
+ break;
+
+ case FASTI2C_STATUS_OFFSET:
+ BUG();
+ p->state = ERROR;
+ rc = PORE_ERR_READ_ONLY_REGISTER;
+ break;
+
+ case FASTI2C_DATA_OFFSET:
+ if (len != 8) {
+ rc = PORE_ERR_INVALID_PARAM;
+ break;
+ }
+
+ switch (p->state) {
+
+ case WRITE_DATA_EXPECTED:
+ rc = finalDataWrite(p, buf, 8);
+ p->state = DATA_WRITE_ONGOING;
+ break;
+
+ default:
+ BUG();
+ p->state = ERROR;
+ rc = PORE_ERR_FASTI2C_SEQUENCE_ERROR;
+ break;
+ }
+ break;
+
+ default:
+ return PORE_ERR_NOACK; /* not for this fi2cm */
+ }
+
+ *err_code = PORE_PCB_SUCCESS;
+ return rc;
+}
+
+struct pore_bus *poreb_create_fi2c(const char *name,
+ uint8_t *mem_buf,
+ unsigned int mem_size,
+ unsigned int mem_start,
+ unsigned int prv_port,
+ unsigned int address_bytes,
+ unsigned int i2c_port,
+ unsigned int deviceAddress)
+{
+ struct pore_bus *b;
+ struct fi2c *e;
+
+ b = poreb_create(name, sizeof(*e), fi2c_read, fi2c_write,
+ NULL, NULL);
+ if (!b)
+ return NULL;
+
+ e = (struct fi2c *)poreb_get_priv(b);
+ e->bus = b;
+ e->mem_buf = mem_buf;
+ e->mem_size = mem_size;
+ e->mem_start = mem_start;
+ e->address = 0;
+
+ e->prv_port = prv_port;
+ e->addressBytes = address_bytes;
+
+ e->i2c_port = i2c_port;
+ e->deviceAddress = deviceAddress;
+ e->command_completion = 0;
+ e->state = IDLE;
+
+ return b;
+}
diff --git a/src/usr/pore/poreve/pore_model/ibuf/pore_fi2c.h b/src/usr/pore/poreve/pore_model/ibuf/pore_fi2c.h
new file mode 100644
index 000000000..6284e3648
--- /dev/null
+++ b/src/usr/pore/poreve/pore_model/ibuf/pore_fi2c.h
@@ -0,0 +1,47 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/pore_model/ibuf/pore_fi2c.h $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __PORE_FI2C_H__
+#define __PORE_FI2C_H__
+
+/******************************************************************************
+ *
+ * Virtual PORe Engine
+ *
+ *****************************************************************************/
+
+#include <stdint.h>
+
+/* FIXME An I2C controller can support more than one ports and it can
+ * also have more than one device listening on one of those. Just like
+ * real world I2C busses connected to an I2C master with an output
+ * multiplexor. For our purpose one i2c_port with one device address
+ * is enough.
+ */
+struct pore_bus *poreb_create_fi2c(const char *name, uint8_t *mem_buf,
+ unsigned int mem_size,
+ unsigned int prv_port,
+ unsigned int address_bytes,
+ unsigned int i2c_port,
+ unsigned int deviceAddress);
+
+#endif /* __PORE_FI2C_H__ */
diff --git a/src/usr/pore/poreve/pore_model/ibuf/pore_ibuf.h b/src/usr/pore/poreve/pore_model/ibuf/pore_ibuf.h
new file mode 100644
index 000000000..33f9bc30f
--- /dev/null
+++ b/src/usr/pore/poreve/pore_model/ibuf/pore_ibuf.h
@@ -0,0 +1,222 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/pore_model/ibuf/pore_ibuf.h $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __PORE_IBUF_H__
+#define __PORE_IBUF_H__
+
+/******************************************************************************
+ *
+ * Virtual PORe Engine
+ *
+ *****************************************************************************/
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "pore_regs.h"
+#include "pore_model.h"
+#include "pore_wrap.h"
+#include "pore_inline_decode.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// \brief Bit manipulation for Big-Endian data
+
+/// A bit mask for a range of bits in a big-endian uint64_t
+#define BE64_MASK(begin, end) \
+ ((0xffffffffffffffffull >> (64 - ((end) - (begin) + 1))) << (63 - (end)))
+
+/// A single bit mask for a big-endian uint64_t
+#define BE64_BIT(n) (BE64_MASK((n), (n)))
+
+/// Extract an unsigned field from a uint64_t
+#define BE64_GET_FIELD(x, begin, end) \
+ (((x) & BE64_MASK((begin), (end))) >> (63 - (end)))
+
+/// Update an unsigned field in a uint64_t from a right-justified
+/// uint64_t value
+#define BE64_SET_FIELD(x, begin, end, val) \
+ ((((val) << (63 - (end))) & BE64_MASK((begin), (end))) | \
+ ((x) & ~BE64_MASK((begin), (end))))
+
+/// A bit mask for a range of bits in a big-endian uint32_t
+#define BE32_MASK(begin, end) \
+ ((0xffffffff >> (32 - ((end) - (begin) + 1))) << (31 - (end)))
+
+/// A single bit mask for a big-endian uint32_t
+#define BE32_BIT(n) (BE32_MASK((n), (n)))
+
+/// Extract an unsigned field from a uint32_t
+#define BE32_GET_FIELD(x, begin, end) \
+ (((x) & BE32_MASK((begin), (end))) >> (31 - (end)))
+
+/// Update an unsigned field in a uint32_t from a right-justified
+/// uint32_t value
+#define BE32_SET_FIELD(x, begin, end, val) \
+ ((((val) << (31 - (end))) & BE32_MASK((begin), (end))) | \
+ ((x) & ~BE32_MASK((begin), (end))))
+
+// State Definitions. These are the values of the status register
+// 'State machine current state' field, that includes the PORE state
+// machine state as bits 3:6. When the PORE is running, we report it
+// as being in state EXEC. ABR is the address breakpoint state.
+
+#define PORE_STATE_WAIT 0x02
+#define PORE_STATE_EXEC 0x0e
+#define PORE_STATE_ABR 0x16
+
+/// The number of PORE error vectors
+#define PORE_ERROR_VECTORS 5
+
+/// The number of PORE EXE vectors
+#define PORE_EXE_VECTORS 16
+
+/// The size of a PORE BRAI instruction in bytes
+#define PORE_VECTOR_SIZE 12
+
+/// Branch modes for Hook implementation
+#define FORCED_BRANCH_DISALLOWED 0
+#define FORCED_BRANCH_FETCH_HOOK 1
+#define FORCED_BRANCH_HOOK_INSTRUCTION 2
+
+/* Main data of the pore_model hidden from the users */
+struct pore_model {
+ /* PORe State (for backup/restore) ----------------------------------*/
+ pore_status_reg status; /* 0x00000000 */
+ pore_control_reg control; /* 0x00000008 */
+ pore_reset_reg reset; /* 0x00000010 */
+ pore_error_mask_reg error_mask; /* 0x00000018 */
+ pore_prv_base_address_reg prv_base[2]; /* 0x00000020 *
+ * 0x00000028 */
+ pore_oci_base_address_reg oci_base[2]; /* 0x00000030
+ * 0x00000038 */
+ pore_table_base_addr_reg table_base_addr; /* 0x00000040 */
+ pore_exe_trigger_reg exe_trigger; /* 0x00000048 */
+ pore_scratch0_reg scratch0; /* 0x00000050 */
+ uint64_t scratch1; /* 0x00000058 */
+ uint64_t scratch2; /* 0x00000060 */
+ pore_ibuf_01_reg ibuf_01; /* 0x00000068 */
+ pore_ibuf_2_reg ibuf_2; /* 0x00000070 */
+ pore_dbg0_reg dbg0; /* 0x00000078 */
+ pore_dbg1_reg dbg1; /* 0x00000080 */
+ pore_pc_stack0_reg pc_stack[3]; /* 0x00000088 *
+ * 0x00000090 *
+ * 0x00000098 */
+ pore_id_flags_reg id_flags; /* 0x000000a0 */
+ uint64_t data0; /* 0x000000a8 */
+ pore_memory_reloc_reg memory_reloc; /* 0x000000b0 */
+ pore_i2c_en_param_reg i2c_e_param[3]; /* 0x000000b8 *
+ * 0x000000c0 *
+ * 0x000000c8 */
+ uint64_t branchTaken; /* last ins branch? pc updated? d0 */
+ uint64_t broken; /* in case we ran on a breakpoint d8 */
+ uint32_t oci_fetchBufferValid; /* 0x000000e0 */
+ uint32_t oci_fetchBufferCursor;
+ uint64_t oci_fetchBuffer; /* 0x000000e8 */
+ /* backup state ends here ------------------------------------------ */
+
+ const char *name;
+ void *priv;
+ int state;
+ int err_code;
+ uint64_t trace_flags;
+
+ /* disassembler support */
+ unsigned int opcode_len;
+ PoreInlineDecode dis;
+
+ int enableTrap; /* FIXME discuss this interface */
+ int singleStep; /* FIXME discuss this interface */
+ uint64_t stack_pointer;
+
+ /* Hook support */
+ uint64_t forcedPc;
+ int forcedBranch; /* FIXME discuss this interface */
+ int forcedBranchMode; /* FIXME discuss this interface */
+
+ int enableHookInstruction;
+ instrHook_f instrHook;
+
+ int enableAddressHooks;
+ readHook_f readHook;
+ writeHook_f writeHook;
+ fetchHook_f fetchHook;
+ decodeHook_f decodeHook;
+
+ waitCallback_f waitCallback;
+ errorCallback_f errorCallback;
+ errorCallback_f fatalErrorCallback;
+
+ /* address translation objects */
+ struct pore_bus *pib; /* Pervasive Interconnect Bus */
+ struct pore_bus *mem; /* OCI or FI2C */
+};
+
+/* address conversion from pore to oci */
+struct pore_bus *poreb_create_pore2oci(struct pore_model *pore,
+ const char *name,
+ struct pore_bus *oci);
+
+/* attach the three fi2c-masters to the pore-model */
+struct pore_bus *poreb_create_pore2fi2c(struct pore_model *pore,
+ const char *name,
+ struct pore_bus *fi2c0,
+ struct pore_bus *fi2c1,
+ struct pore_bus *fi2c2);
+
+/* fast i2cm connected to pib bus */
+struct pore_bus *poreb_create_fi2cm(struct pore_model *pm, const char *name,
+ pore_bus_t pib,
+ pore_i2c_en_param_reg *i2c_param);
+
+int pore_handleErrEvent(pore_model_t p, int error_in, int model_err);
+
+/**
+ * @brief Attach PIB bus to PORe model.
+ *
+ * @param [in] p reference to PORe model
+ * @param [in] b referenct to PIB bus-object
+ */
+int pore_attach_pib (pore_model_t p, struct pore_bus *b);
+
+/**
+ * @brief Direct read access to PIB bus e.g. for fi2cm or scand
+ * operations.
+ */
+int pore_pib_read (pore_model_t p, uint64_t pib_addr, uint8_t *buf,
+ unsigned int len, int *err_code);
+
+/**
+ * @brief Direct write access to PIB bus e.g. for fi2cm or scand
+ * operations.
+ */
+int pore_pib_write (pore_model_t p, uint64_t pib_addr, const uint8_t *buf,
+ unsigned int len, int *err_code);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PORE_IBUF_H__ */
diff --git a/src/usr/pore/poreve/pore_model/ibuf/pore_inline_decode.c b/src/usr/pore/poreve/pore_model/ibuf/pore_inline_decode.c
new file mode 100644
index 000000000..d2574fa80
--- /dev/null
+++ b/src/usr/pore/poreve/pore_model/ibuf/pore_inline_decode.c
@@ -0,0 +1,129 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/pore_model/ibuf/pore_inline_decode.c $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#include <stdint.h>
+#include "pore_inline_decode.h"
+
+// From a uint32_t, extract a big-endian bit x[i] as either 0 or 1
+
+#define BE_BIT_32(x, i) (((x) >> (31 - (i))) & 1)
+
+
+// From a uint32_t, extract big-endian bits x[first:last] as unsigned to
+// create a uint32_t.
+
+#define BE_BITS_32_UNSIGNED(x, first, last) \
+ (((x) >> (31 - (last))) & (0xffffffff >> (32 - (last - first + 1))))
+
+
+// From a uint32_t, extract big-endian bits x[first:last] as signed to create
+// an int32_t.
+
+#define BE_BITS_32_SIGNED(x, first, last) \
+ (((x) & (1 << (31 - (first)))) ? \
+ (BE_BITS_32_UNSIGNED(x, first, last) | (0xffffffff << (31 - first))) : \
+ BE_BITS_32_UNSIGNED(x, first, last))
+
+/// Install and decode an instruction into the PoreInlineDissassembly object
+///
+/// \param dis A PoreInlineDisassembly structure to contain the disassembled
+/// instruction.
+///
+/// \param instruction The initial (or only) 32 bits of a PORE instruction
+///
+/// For simplicity, instructions are currently (almost) fully decoded for all
+/// possible formats. It is up to the application using this API to further
+/// decode the actual opcode to determine which of these fields are valid for
+/// the current instruction.
+///
+/// To simplify parity calculations the \a imd64 field is cleared here. A
+/// companion API pore_inline_decode_imd64() is used to decode the final 64
+/// bits of long instructions.
+///
+/// This API is designed to be called independently of the full disassembler,
+/// in which case any fields of \a dis not explicitly set will be undefined.
+
+void
+pore_inline_decode_instruction(PoreInlineDecode *dis, uint32_t instruction)
+{
+ dis->instruction = instruction;
+
+ // Generic decoding
+ dis->opcode = BE_BITS_32_UNSIGNED(instruction, 0, 6);
+ dis->long_instruction = BE_BIT_32(instruction, 0);
+ dis->parity = BE_BITS_32_UNSIGNED(instruction, 7, 7);
+ dis->memory_space = BE_BIT_32(instruction, 8);
+ dis->update = BE_BIT_32(instruction, 8);
+ dis->capture = BE_BIT_32(instruction, 9);
+ dis->imd16 = BE_BITS_32_SIGNED(instruction, 16, 31);
+ dis->scan_length = BE_BITS_32_UNSIGNED(instruction, 16, 31);
+ dis->imd20 = BE_BITS_32_SIGNED(instruction, 12, 31);
+ dis->imd24 = dis->ima24 = BE_BITS_32_UNSIGNED(instruction, 8, 31);
+ dis->impco20 = BE_BITS_32_SIGNED(instruction, 12, 31);
+ dis->impco24 = BE_BITS_32_SIGNED(instruction, 8, 31);
+ dis->tR = dis->r0 = BE_BITS_32_UNSIGNED(instruction, 8, 11);
+ dis->sR = dis->r1 = BE_BITS_32_UNSIGNED(instruction, 12, 15);
+ dis->imd64 = 0;
+
+ // imA24 decoding
+ if (dis->memory_space) {
+ dis->base_register =
+ BE_BIT_32(instruction, 9) ?
+ PORE_OCI_MEMORY_BASE_ADDR1_ENC :
+ PORE_OCI_MEMORY_BASE_ADDR0_ENC;
+
+ dis->memory_offset =
+ BE_BITS_32_UNSIGNED(dis->instruction, 10, 31);
+ } else {
+ dis->base_register =
+ BE_BIT_32(instruction, 9) ?
+ PORE_PRV_BASE_ADDR1_ENC :
+ PORE_PRV_BASE_ADDR0_ENC;
+
+ dis->pib_offset =
+ BE_BITS_32_UNSIGNED(dis->instruction, 12, 31);
+ }
+}
+
+
+/// Install and decode an imd64 into a PoreInlineDissassembly object
+///
+/// \param dis A PoreInlineDisassembly structure to contain the disassembled
+/// data
+///
+/// \param imd64 The final 64 bits of a 12-byte PORE instruction
+///
+/// For simplicity, instructions are currently (almost) fully decoded for all
+/// possible formats. It is up to the application to determine which if any of
+/// these fields are valid for the current instruction.
+///
+/// This API is designed to be called independently of the full disassembler,
+/// in which case any fields of \a dis not explicitly set will be undefined.
+
+void
+pore_inline_decode_imd64(PoreInlineDecode *dis, uint64_t imd64)
+{
+ dis->imd64 = imd64;
+ dis->impc48 = dis->imd64 & 0xffffffffffffull;
+ dis->scan_select = imd64 >> 32;
+ dis->scan_offset = imd64 & 0xffffffff;
+}
diff --git a/src/usr/pore/poreve/pore_model/ibuf/pore_inline_decode.h b/src/usr/pore/poreve/pore_model/ibuf/pore_inline_decode.h
new file mode 100644
index 000000000..d34317903
--- /dev/null
+++ b/src/usr/pore/poreve/pore_model/ibuf/pore_inline_decode.h
@@ -0,0 +1,207 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/pore_model/ibuf/pore_inline_decode.h $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __PORE_INLINE_DECODE_H__
+#define __PORE_INLINE_DECODE_H__
+
+#include <stdint.h>
+#include "pore_inline_decode.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* latest definitions can be found in pgas.h */
+#define PORE_OPCODE_NOP 0x0f
+#define PORE_OPCODE_WAIT 0x01
+#define PORE_OPCODE_TRAP 0x02
+#define PORE_OPCODE_HOOK 0x4f
+
+#define PORE_OPCODE_BRA 0x10
+#define PORE_OPCODE_BRAZ 0x12
+#define PORE_OPCODE_BRANZ 0x13
+#define PORE_OPCODE_BRAI 0x51
+#define PORE_OPCODE_BSR 0x14
+#define PORE_OPCODE_BRAD 0x1c
+#define PORE_OPCODE_BSRD 0x1d
+#define PORE_OPCODE_RET 0x15
+#define PORE_OPCODE_CMPBRA 0x56
+#define PORE_OPCODE_CMPNBRA 0x57
+#define PORE_OPCODE_CMPBSR 0x58
+#define PORE_OPCODE_LOOP 0x1f
+
+#define PORE_OPCODE_ANDI 0x60
+#define PORE_OPCODE_ORI 0x61
+#define PORE_OPCODE_XORI 0x62
+
+#define PORE_OPCODE_AND 0x25
+#define PORE_OPCODE_OR 0x26
+#define PORE_OPCODE_XOR 0x27
+
+#define PORE_OPCODE_ADD 0x23
+#define PORE_OPCODE_ADDI 0x24
+#define PORE_OPCODE_SUB 0x29
+#define PORE_OPCODE_SUBI 0x28
+#define PORE_OPCODE_NEG 0x2a
+
+#define PORE_OPCODE_COPY 0x2c
+#define PORE_OPCODE_ROL 0x2e
+
+#define PORE_OPCODE_LOAD20 0x30
+#define PORE_OPCODE_LOAD64 0x71
+#define PORE_OPCODE_SCR1RD 0x32
+#define PORE_OPCODE_SCR1RDA 0x73
+#define PORE_OPCODE_SCR2RD 0x36
+#define PORE_OPCODE_SCR2RDA 0x77
+#define PORE_OPCODE_WRI 0x78
+#define PORE_OPCODE_BS 0x74
+#define PORE_OPCODE_BC 0x75
+#define PORE_OPCODE_SCR1WR 0x39
+#define PORE_OPCODE_SCR2WR 0x3a
+#define PORE_OPCODE_SCAND 0x7c
+
+#ifndef __ASSEMBLER__
+
+/* Internal register encodings for the execution engine */
+typedef enum {
+ PORE_PRV_BASE_ADDR0_ENC = 0x00,
+ PORE_PRV_BASE_ADDR1_ENC = 0x01,
+ PORE_OCI_MEMORY_BASE_ADDR0_ENC = 0x02,
+ PORE_OCI_MEMORY_BASE_ADDR1_ENC = 0x03,
+ PORE_SCRATCH0_ENC = 0x04,
+ PORE_SCRATCH1_ENC = 0x05,
+ PORE_SCRATCH2_ENC = 0x06,
+ PORE_ERROR_MASK_ENC = 0x07,
+ /* PORE_MEM_RELOC_ENC = 0x07, */
+ PORE_TABLE_BASE_ADDR_ENC = 0x08,
+ PORE_EXE_TRIGGER_ENC = 0x09,
+ PORE_DATA0_ENC = 0x0a,
+ /* PORE_I2C_E0_PARAM_ENC = 0x0b, */
+ /* PORE_I2C_E1_PARAM_ENC = 0x0c, */
+ /* PORE_I2C_E2_PARAM_ENC = 0x0d, */
+ PORE_PC_ENC = 0x0e,
+ PORE_ALU_IBUF_ID_ENC = 0x0f
+} pore_internal_reg_t;
+
+typedef struct {
+
+ /// The first 32 bits of every instruction
+ uint32_t instruction;
+
+ /// The opcode; bits 0..6 of the instruction
+ int opcode;
+
+ // Is this instruction 4 or 12 bytes long; bit 0 of the instruction
+ int long_instruction;
+
+ // bit 8 of the instruction which is within the ima24 address
+ int memory_space;
+
+ /// The parity bit; bit 7 of the instruction
+ int parity;
+
+ /// The register specifier at bits 8..11 of the instruction
+ ///
+ /// This register is sometimes called the source, sometimes the target,
+ /// depending on the opcode.
+ int tR;
+ int r0;
+
+ /// The register specifier at bits 12..15 of the instruction
+ ///
+ /// This register is always called the 'source' but is named generically
+ /// here since sometimes the specifier at bits 8..11 is also called a
+ /// 'source'.
+ int sR;
+ int r1;
+
+ /// 'ImD16' is the signed 16-bit immediate for short immediate adds and
+ /// subtracts. For the rotate instruction this field also contains the
+ /// rotate count which is either 1, 4, 8, 16 or 32.
+ int16_t imd16;
+
+ /// 'ImD20' is the 20-bit unsigned immediate for the LOAD20 instruction
+ int32_t imd20;
+
+ /// 'ImD24' is the 24-bit unsigned immediate for the WAIT instruction
+ uint32_t imd24;
+
+ /// 'ImA24' is the 24-bit unsigned immediate representing an address
+ uint32_t ima24;
+
+ /// 'ImD64' is the 64-bit immediate for data immediates and BRAI. This
+ /// field is only set for 3-word instructions.
+ uint64_t imd64;
+
+ /// 'ImPCO20' is a signed, 20-bit word offset for branch instructions
+ int32_t impco20;
+
+ /// 'ImPCO24' is a signed, 24-bit word offset for branch instructions
+ int32_t impco24;
+
+ /// 'ImPC48' is a signed, 48-bit word offset for branch instructions
+ int64_t impc48;
+
+ /// This is the base register specifier - either a memory (OCI) base
+ /// register or a pervasive base register - for Read/Write operations.
+ int base_register;
+
+ /// This is the 22-bit signed offset for memory (OCI) addressing
+ int32_t memory_offset;
+
+ /// This field contains the port number and local address portions of the
+ /// PIB/PCB address for load/store operations that target the PIB/PCB.
+ /// Note that bits 0..11 will always be 0 in this address. Bits 1..7 (the
+ /// multicast bit and chiplet id) are sourced from the associated
+ /// pervasive base register when the instruction executes.
+ uint32_t pib_offset;
+
+ /// The update bit of the SCAND instruction
+ int update;
+
+ /// The capture bit of the SCAND instruction
+ int capture;
+
+ /// The scan length from a SCAND instruction
+ int scan_length;
+
+ /// The scan select from a SCAND instruction
+ uint32_t scan_select;
+
+ /// The address offset from a SCAND instruction
+ uint32_t scan_offset;
+
+} PoreInlineDecode;
+
+void
+pore_inline_decode_instruction(PoreInlineDecode *dis, uint32_t instruction);
+
+void
+pore_inline_decode_imd64(PoreInlineDecode *dis, uint64_t imd64);
+
+#ifdef __cplusplus
+} /* closing brace for extern "C" */
+#endif
+
+#endif /* __ASSEMBLER__ */
+
+#endif /* __PORE_INLINE_DECODE_H__ */
diff --git a/src/usr/pore/poreve/pore_model/ibuf/pore_model.c b/src/usr/pore/poreve/pore_model/ibuf/pore_model.c
new file mode 100644
index 000000000..f5306fdb5
--- /dev/null
+++ b/src/usr/pore/poreve/pore_model/ibuf/pore_model.c
@@ -0,0 +1,3130 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/pore_model/ibuf/pore_model.c $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+/******************************************************************************
+ *
+ * Virtual PORe Engine
+ *
+ *****************************************************************************/
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pore_regs.h"
+#include "pore_ibuf.h"
+#include "pore_model.h"
+#include "pore_inline_decode.h"
+
+static int fetch(pore_model_t p);
+static int decode(pore_model_t p);
+static int execute(pore_model_t p);
+static int finishBrokenInstruction(pore_model_t p);
+
+#define PORE_GET_BITS(X,S,N) \
+ ((((~(0xFFFFFFFFFFFFFFFFull >> (N))) >> (S)) \
+ & (X)) >> (64 - (S)-(N)))
+#define PORE_SET_BITS(Y,X,S,N,V) \
+ Y = (((X) & (~((~((~0x0)<<(N))) << (64-(S)-(N))))) | \
+ (((~(0xFFFFFFFFFFFFFFFFull << (N))) & (V)) << (64 - (S)-(N))))
+
+#define PORE_GET_BIT(X,S) PORE_GET_BITS((X),(S),1)
+#define PORE_SET_BIT(Y,X,S,V) PORE_SET_BITS(Y,(X),(S),1,(V))
+
+/* Exception handling ********************************************************/
+
+/// Set the PC to the Nth combined vector
+static int
+pore_vectorThroughTable(pore_model_t p, unsigned vector)
+{
+ uint32_t offset;
+
+ if (vector >= (PORE_ERROR_VECTORS + PORE_EXE_VECTORS)) {
+ BUG();
+ return PORE_ERR_BUG_INVALID_VECTOR;
+ }
+ offset = p->table_base_addr.table_base_address +
+ (vector * PORE_VECTOR_SIZE);
+
+ p->status.pc = ((uint64_t)p->table_base_addr.memory_space << 32) +
+ offset;
+
+ dprintf(p, "%s: Jumping to vector %d @ %016llx\n",
+ __func__, vector, (long long)p->status.pc);
+
+ return PORE_SUCCESS;
+}
+
+/// Set the PC to an error vector
+static inline int
+pore_errorVector(pore_model_t p, unsigned error)
+{
+ return pore_vectorThroughTable(p, error);
+}
+
+/// Set the PC to an EXE vector
+static int
+pore_exeVector(pore_model_t p, unsigned vector)
+{
+ return pore_vectorThroughTable(p, PORE_ERROR_VECTORS + vector);
+}
+
+/* Support read/write registers with side effects ****************************/
+
+static inline int
+pore_stack0_reg_write(pore_model_t p, uint64_t val, uint64_t mask)
+{
+ int me = PORE_SUCCESS;
+ int newSp;
+ pore_pc_stack0_reg pps0;
+
+ val &= PORE_PC_STACK0_VALID_BITS;
+ p->pc_stack[0].val = ((val & mask) |
+ (p->pc_stack[0].val & ~mask));
+ p->pc_stack[0].set_stack_pointer = 0;
+ p->pc_stack[0].new_stack_pointer = 0;
+
+ pps0.val = val & mask;
+ if (pps0.set_stack_pointer) {
+ newSp = pps0.new_stack_pointer;
+ if ((newSp != 0) &&
+ (newSp != 1) &&
+ (newSp != 2) &&
+ (newSp != 4)) {
+ me = PORE_ERR_INVALID_STACK_POINTER;
+ } else {
+ p->status.stack_pointer = newSp;
+ }
+ }
+ return me;
+}
+
+// NB: Technically, if the PORE is being held in reset no other
+// register updates should go through or have effect. We don't model
+// that, however, and instead just catch cases where firmware tries to
+// execute PORE programs while PORE or the OCI master are in reset.
+
+static inline int
+pore_reset_reg_write(pore_model_t p, uint64_t val, uint64_t mask)
+{
+ pore_reset_reg reset;
+
+ dprintf(p, "%s: val=%016llx mask=%016llx\n", __func__,
+ (long long)val, (long long)mask);
+
+ val &= PORE_RESET_VALID_BITS;
+ reset.val = ((val & mask) |
+ (p->reset.val & ~mask));
+
+ if (mask & PORE_BITS_0_31) {
+ if (reset.fn_reset)
+ return pore_flush_reset(p);
+ if (reset.oci_reset)
+ return poreb_reset(p->mem);
+ if (reset.restart_sbe_trigger) {
+ /* FIXME SBE will reset and restart initial
+ * boot code execution
+ */
+ return pore_flush_reset(p);
+ }
+ }
+
+ /* The bits of this register are self clearing after the
+ * resets have been performed. Don't write bits back.
+ */
+ return PORE_SUCCESS;
+}
+
+static inline void
+pore_status_reg_print(pore_status_reg *status)
+{
+ aprintf(" PORE_STATUS %016llx\n"
+ " cur_state = %02x freeze_action = %x\n"
+ " stack_pointer = %x pc = %llx\n",
+ (long long)status->val,
+ (unsigned int)status->cur_state,
+ (unsigned int)status->freeze_action,
+ (unsigned int)status->stack_pointer,
+ (long long)status->pc);
+}
+
+static inline void
+pore_control_reg_print(pore_control_reg *poreControl)
+{
+ aprintf(" PORE_CONTROL %016llx\n"
+ " start_stop = %x continue_step = %x\n"
+ " skip = %x set_pc = %x\n"
+ " lock_exe_trig = %x trap_enable = %x\n"
+ " pc_brk_pt = %llx\n",
+ (long long)poreControl->val,
+ (unsigned int)poreControl->start_stop,
+ (unsigned int)poreControl->continue_step,
+ (unsigned int)poreControl->skip,
+ (unsigned int)poreControl->set_pc,
+ (unsigned int)poreControl->lock_exe_trig,
+ (unsigned int)poreControl->trap_enable,
+ (long long)poreControl->pc_brk_pt);
+}
+
+
+/// Control register write side effects
+///
+/// \bug This model is not correct (does not implement) all cases
+/// regarding stopping/starting/continue/breakpoints/traps. This is a
+/// low priority since OCC firmware is not expected to use these
+/// features.
+
+static inline int
+pore_control_reg_write(pore_model_t p, uint64_t val, uint64_t mask)
+{
+ int me = PORE_SUCCESS;
+ int squashWrite = 0;
+ pore_control_reg poreControl;
+
+ poreControl.val = val;
+
+ if (p->trace_flags & PORE_TRACE_IBUF)
+ pore_control_reg_print(&poreControl);
+
+ if (p->reset.fn_reset == 1) {
+ return PORE_ERR_IN_RESET;
+ }
+
+ // Move the value to a local base register for field decoding,
+ // then process control actions.
+ if (mask & PORE_BITS_0_31) {
+
+ // Processing Set PC. This only happens on 64-bit
+ // writes!!! And if it happens, everything else is
+ // ignored. It is considered a firmware error to set
+ // the PC when the hardware is not in the wait state.
+ if (poreControl.set_pc && (mask & PORE_BITS_32_63)) {
+ squashWrite = 1;
+ if ((p->control.start_stop != 1) ||
+ (p->status.cur_state != PORE_STATE_WAIT)) {
+ me = PORE_ERR_NOT_STOPPED_WAIT;
+ } else {
+ p->status.pc = poreControl.pc_brk_pt;
+ }
+ } else {
+ // Processing START/STOP bit. If this bit is
+ // set the PORE stops in the WAIT state. If
+ // we were in the ABR state we have to finish
+ // the instruction first.
+
+ if (poreControl.start_stop) {
+ p->status.cur_state = PORE_STATE_WAIT;
+ } else if (p->status.cur_state == PORE_STATE_WAIT) {
+ p->status.cur_state = PORE_STATE_EXEC;
+ }
+
+ // Hitting the continue bit will restart a
+ // machine in the ABR (address breakpoint)
+ // state. If in any other state we punt.
+
+ if (poreControl.continue_step) {
+ if (p->status.cur_state == PORE_STATE_ABR) {
+ p->status.cur_state = PORE_STATE_EXEC;
+ finishBrokenInstruction(p);
+
+ } else {
+ me = PORE_ERR_BEHAVIOR_NOT_MODELED;
+ }
+ }
+
+ if (poreControl.skip) {
+ me = PORE_ERR_BEHAVIOR_NOT_MODELED;
+ }
+ }
+ }
+
+ if (!me && !squashWrite) {
+
+ // Clear any 'pulse-mode' bits in the register before writing
+ poreControl.continue_step = 0;
+ poreControl.skip = 0;
+ poreControl.set_pc = 0;
+
+ p->control.val = ((poreControl.val & mask) | /* new val */
+ (p->control.val & ~mask)); /* old val */
+
+ dprintf(p, " new control reg val=%016llx\n",
+ (long long)p->control.val);
+ }
+
+ return me;
+}
+
+/// EXE_Trigger Register Write Function
+///
+/// This function writes to the Exe trigger register and also schedules
+/// the instruction for execution when LO order word is written. No side
+/// effect when HI order word is written.
+
+static inline int
+pore_exe_trigger_reg_write(pore_model_t p, uint64_t val, uint64_t mask)
+{
+ int me = PORE_SUCCESS;
+
+ val &= PORE_EXE_TRIGGER_VALID_BITS;
+ if (p->reset.fn_reset == 1) {
+ me = PORE_ERR_IN_RESET;
+
+ } else if (mask == PORE_BITS_32_63) {
+ p->exe_trigger.val = ((val & mask) |
+ (p->exe_trigger.val & ~mask));
+
+ } else if (p->control.lock_exe_trig) {
+ me = PORE_ERR_REGISTER_LOCKED;
+
+ } else {
+ p->exe_trigger.val = ((val & mask) |
+ (p->exe_trigger.val & ~mask));
+
+ // Lock the EXE_TRIGGER register, compute the
+ // new starting PC, and begin execution.
+
+ p->control.lock_exe_trig = 1;
+ p->control.start_stop = 0;
+ pore_exeVector(p, p->exe_trigger.start_vector);
+ }
+ return me;
+}
+
+/// write method for IBUF_01 register. Upon write to the ibuf_0 part
+/// it executes the instruction.
+/// The PORE IBUF0,1,2 registers are read-only, when Instruction
+/// engine is in automatic run-mode (Control Register(0) = 0).
+
+static int
+pore_ibuf_01_reg_write(pore_model_t p, uint64_t val, uint64_t mask)
+{
+ int me = PORE_SUCCESS;
+
+ if (p->reset.fn_reset == 1) {
+ return PORE_ERR_IN_RESET;
+ }
+ if (p->control.start_stop != 1) {
+ return PORE_ERR_NOT_STOPPED;
+ }
+
+ p->ibuf_01.val = ((val & mask) |
+ (p->ibuf_01.val & ~mask));
+
+ if (mask & PORE_BITS_0_31) {
+ me = decode(p);
+ if (me != PORE_SUCCESS)
+ return me;
+
+ me = execute(p);
+ if (me != PORE_SUCCESS)
+ return me;
+
+ /* FIXME In case of stuffing instructions I strongly
+ assume that the PC must not be upated. */
+ }
+ return me;
+}
+
+void pore_set_trace(pore_model_t pm, uint64_t trace)
+{
+ pm->trace_flags = trace;
+}
+
+uint64_t pore_get_trace(pore_model_t pm)
+{
+ return pm->trace_flags;
+}
+
+int pore_instrHook(pore_model_t p, uint64_t addr,
+ uint32_t im24, uint64_t im64)
+{
+ if (!p->instrHook)
+ return 0;
+ return p->instrHook(p, addr, im24, im64);
+}
+
+int pore_readHook(pore_model_t p, uint64_t addr)
+{
+ if (!p->readHook)
+ return 0;
+ return p->readHook(p, addr);
+}
+
+int pore_writeHook(pore_model_t p, uint64_t addr)
+{
+ if (!p->writeHook)
+ return 0;
+ return p->writeHook(p, addr);
+}
+
+int pore_fetchHook(pore_model_t p, uint64_t addr)
+{
+ if (!p->fetchHook)
+ return 0;
+ return p->fetchHook(p, addr);
+}
+
+static int pore_decodeHook(pore_model_t p, uint8_t *instr, unsigned int size)
+{
+ if (!p->decodeHook)
+ return 0;
+ return p->decodeHook(p, instr, size);
+}
+
+static void pore_waitCallback(pore_model_t p, uint32_t delay)
+{
+ if (!p->waitCallback)
+ return;
+ p->waitCallback(p, delay);
+}
+
+static void incrPc(pore_model_t p)
+{
+ p->status.pc += p->opcode_len;
+}
+
+static void setJmpTarget(int offset, PoreAddress *next_pc)
+{
+ next_pc->offset += offset * 4;
+}
+
+/**
+ * Implements Add Operation with Status Flag Set.
+ * This function received the pre constructed operands for ADD and calculates
+ * ALU Status flags. It also updates the id_flags register.
+ * \param op1 operand 1
+ * \param op2 operand 2
+ * \param result result of operaton
+ * \param opcode opcode which was executed
+ * (e.g. SUBx will change g* and s* flags)
+ * \retval PORE_SUCCESS
+ * \todo Make match VHDL model - several issues to resolve.
+ *
+ * See also: Table 4.7: Ibuf internal register: ALU flags and Ibuf-ID.
+ */
+static int setAluFlags(pore_model_t p, int64_t op1, int64_t op2,
+ int64_t result, int opcode)
+{
+ PoreInlineDecode *dis = &p->dis;
+ pore_id_flags_reg *id_flags = &p->id_flags;
+
+ /* Flags are updated only when target is scr1 or src2 */
+ if (dis->tR != PORE_SCRATCH1_ENC && dis->tR != PORE_SCRATCH2_ENC) {
+ return PORE_SUCCESS;
+ }
+
+ /* N: bit 0 of result goes to N; is result negative? */
+ id_flags->n = PORE_GET_BIT(result, 0);
+
+ /* Z: set zero bit */
+ if (result == 0) {
+ id_flags->z = 1;
+ } else {
+ id_flags->z = 0;
+ }
+
+ /* O: check for overflows */
+ if ((~((op1 ^ op2) >> 63) & 0x1ull) &
+ (((result ^ op1) >> 63) & 0x1ull)) {
+ id_flags->o = 1;
+ } else {
+ id_flags->o = 0;
+ }
+
+ /* C: set carry bit */
+ if (((op1 & 0x7fffffffffffffffull) +
+ (op2 & 0x7FFFFFFFFFFFFFFFull)) & (0x1ull << 63)) {
+
+ if ((PORE_GET_BIT(op1,0) + PORE_GET_BIT(op2,0) + 1 ) >> 1) {
+ id_flags->c = 1;
+ } else {
+ id_flags->c = 0;
+ }
+ } else {
+ if ((PORE_GET_BIT(op1,0) + PORE_GET_BIT(op2,0) ) >> 1) {
+ id_flags->c = 1;
+ } else {
+ id_flags->c = 0;
+ }
+
+ }
+
+ /* UGT, ULT, SGT, SLT */
+ if ((opcode == PORE_OPCODE_SUB) ||
+ (opcode == PORE_OPCODE_SUBI)) {
+ /* UGT = C AND !Z */
+ id_flags->ugt = ((id_flags->c & ~id_flags->z) & 0x1);
+
+ /* ULT = !C AND !Z */
+ id_flags->ult = ((~id_flags->c & ~id_flags->z) & 0x1);
+
+ /* SGT = (N AND V AND !Z) OR (!N AND !V AND !Z)
+ */
+ id_flags->sgt = (((id_flags->n &
+ id_flags->o &
+ ~id_flags->z) & 0x1) |
+ ((~id_flags->n &
+ ~id_flags->o &
+ ~id_flags->z) & 0x1));
+
+ /* SLT = (N AND !V) OR (!N AND V) */
+ id_flags->slt = (((id_flags->n & ~id_flags->o) & 0x1 ) |
+ ((~id_flags->n & id_flags->o) & 0x1 ));
+ }
+ /* If the instruction is an ADD, then by specification the
+ * UGT/ULT/SGT/SLT bits are cleared.
+ */
+ else if ((opcode == PORE_OPCODE_ADD) ||
+ (opcode == PORE_OPCODE_ADDI)) {
+ id_flags->ugt = 0;
+ id_flags->ult = 0;
+ id_flags->sgt = 0;
+ id_flags->slt = 0;
+ }
+
+ return 0;
+}
+
+/*** Address Decoding ********************************************************/
+
+/// Relocate a memory address if it's in the relocation region
+void pore_relocateAddress(pore_model_t p, uint64_t *addr)
+{
+ PoreAddress address;
+
+ address.val = *addr;
+
+ if (p->memory_reloc.memory_reloc_region == (address.offset >> 30)) {
+ address.offset += (p->memory_reloc.memory_reloc_base << 12);
+ }
+ *addr = address.val;
+}
+
+/// Compute OCI effective and real addresses and handle hooks. The
+/// returned address is the real (physical) PoreAddress.
+static int computeOciDataAddress(pore_model_t p, uint32_t ima24,
+ PoreAddress *address, int read_not_write)
+{
+ uint32_t base_select = ima24 & 0x400000;
+ pore_oci_base_address_reg oci_base;
+
+ // First compute an effective address. The 'oci_mem_route' is
+ // in the form of a memory space descriptor, minus the
+ // high-order bit. This memory route is only used in the
+ // PORE-SBE.
+
+ if (base_select) {
+ oci_base.val = p->oci_base[1].val;
+ } else {
+ oci_base.val = p->oci_base[0].val;
+ }
+
+ address->memorySpace = oci_base.oci_mem_route | 0x8000;
+ address->offset = oci_base.oci_base_address + (ima24 & 0x003FFFFF);
+
+ if (pore_get_enableAddressHooks(p)) {
+ if (read_not_write) {
+ pore_readHook(p, address->val);
+ } else {
+ pore_writeHook(p, address->val);
+ }
+ }
+
+ // Return the relocated address
+ pore_relocateAddress(p, &address->val);
+ return 0;
+}
+
+/* Internal register encodings ***********************************************/
+
+static uint64_t __readReg(pore_model_t p, pore_internal_reg_t reg)
+{
+ switch (reg) {
+ case PORE_PRV_BASE_ADDR0_ENC: return p->prv_base[0].val >> 32;
+ case PORE_PRV_BASE_ADDR1_ENC: return p->prv_base[1].val >> 32;
+ case PORE_OCI_MEMORY_BASE_ADDR0_ENC: return p->oci_base[0].val;
+ case PORE_OCI_MEMORY_BASE_ADDR1_ENC: return p->oci_base[1].val;
+ case PORE_TABLE_BASE_ADDR_ENC: return p->table_base_addr.val;
+ case PORE_EXE_TRIGGER_ENC: return p->exe_trigger.val;
+ case PORE_SCRATCH0_ENC: return p->scratch0.val >> 32;
+ case PORE_SCRATCH1_ENC: return p->scratch1;
+ case PORE_SCRATCH2_ENC: return p->scratch2;
+ case PORE_DATA0_ENC: return p->data0 >> 32;
+ case PORE_ERROR_MASK_ENC: return p->error_mask.val;
+ case PORE_PC_ENC: return p->status.pc;
+ case PORE_ALU_IBUF_ID_ENC: return p->id_flags.val;
+ }
+
+ eprintf(p, "%s: err: illegal reg %x\n", __func__, reg);
+ return PORE_ERR_INVALID_PARAM;
+}
+
+static int __writeReg(pore_model_t p, pore_internal_reg_t reg, uint64_t val)
+{
+ switch (reg) {
+ case PORE_PRV_BASE_ADDR0_ENC:
+ p->prv_base[0].val =
+ (val << 32) & PORE_PRV_BASE_ADDRESS_VALID_BITS;
+ break;
+ case PORE_PRV_BASE_ADDR1_ENC:
+ p->prv_base[1].val =
+ (val << 32) & PORE_PRV_BASE_ADDRESS_VALID_BITS;
+ break;
+
+ case PORE_OCI_MEMORY_BASE_ADDR0_ENC:
+ p->oci_base[0].val =
+ val & PORE_OCI_BASE_ADDRESS_VALID_BITS;
+ break;
+ case PORE_OCI_MEMORY_BASE_ADDR1_ENC:
+ p->oci_base[1].val =
+ val & PORE_OCI_BASE_ADDRESS_VALID_BITS;
+ break;
+
+ case PORE_TABLE_BASE_ADDR_ENC:
+ p->table_base_addr.val = val; break;
+ case PORE_EXE_TRIGGER_ENC:
+ /**
+ * A COPY instruction to the EXE_Trigger register will
+ * only update the upper half of the register and not
+ * trigger a new start vector execution.
+ */
+ p->exe_trigger.mc_chiplet_select_mask = val & 0xffffffff;
+ break;
+
+ case PORE_SCRATCH0_ENC:
+ p->scratch0.val = (val << 32) & PORE_SCRATCH0_VALID_BITS;
+ break;
+
+ case PORE_SCRATCH1_ENC:
+ p->scratch1 = val;
+ break;
+ case PORE_SCRATCH2_ENC:
+ p->scratch2 = val;
+ break;
+
+ case PORE_DATA0_ENC:
+ p->data0 = (val << 32) & PORE_DATA0_VALID_BITS;
+ break;
+ case PORE_ERROR_MASK_ENC:
+ p->error_mask.val = val & PORE_ERROR_MASK_VALID_BITS;
+ break;
+ case PORE_PC_ENC: p->status.pc = val; break;
+ case PORE_ALU_IBUF_ID_ENC:
+ p->id_flags.val = val & PORE_ID_FLAGS_VALID_BITS;
+ break;
+ default:
+ eprintf(p, "%s: err: illegal reg %x\n", __func__, reg);
+ return PORE_ERR_INVALID_PARAM;
+ }
+ return PORE_SUCCESS;
+}
+
+/*** Stack operations ********************************************************/
+
+/**
+ * Stack push. Only in the event of an error push do we allow the 3rd
+ * level to be used.
+ *
+ * 0001: Stack empty
+ * 0010: Stack filled up to level 1
+ * 0100: Stack filled up to level 2
+ * 1000: Stack filled up to level 3 (error handler only)
+ */
+static int push(pore_model_t p, uint64_t next_pc, int error)
+{
+ int rc = PORE_SUCCESS;
+ pore_pc_stack0_reg pc_stack0;
+
+ if (p->status.stack_pointer == 0x4) {
+ BUG();
+ p->dbg1.pc_stack_ovflw_undrn_err = 1;
+ p->control.start_stop = 1; /* FIXME This is brute force */
+ return PORE_ERR_STACK_OVERFLOW;
+ }
+
+ if ((p->status.stack_pointer == 0x2) && !error) {
+ p->dbg1.pc_stack_ovflw_undrn_err = 1;
+ rc = pore_handleErrEvent(p, 2, PORE_ERR_STACK_OVERFLOW);
+ if (rc < 0) {
+ return rc;
+ }
+ }
+
+ pc_stack0.val = p->pc_stack[0].val;
+
+ switch (p->status.stack_pointer) {
+ case 0x0:
+ case 0x1:
+ case 0x2:
+ p->pc_stack[2].pc_stack = p->pc_stack[1].pc_stack;
+ p->pc_stack[1].pc_stack = p->pc_stack[0].pc_stack;
+ pc_stack0.pc_stack = next_pc;
+ pore_stack0_reg_write(p, pc_stack0.val, PORE_BITS_0_63);
+
+ p->status.stack_pointer =
+ (p->status.stack_pointer == 0) ? 1 :
+ (p->status.stack_pointer << 1);
+ break;
+ default:
+ return PORE_ERR_INVALID_STACK_POINTER;
+ }
+
+ return PORE_SUCCESS;
+}
+
+/**
+ * Stack pop.
+ *
+ * 0001: Stack empty
+ * 0010: Stack filled up to level 1
+ * 0100: Stack filled up to level 2
+ * 1000: Stack filled up to level 3 (error handler only)
+ */
+static int pop(pore_model_t p, PoreAddress *next_pc)
+{
+ int rc;
+ pore_pc_stack0_reg pc_stack0;
+
+ pc_stack0.val = p->pc_stack[0].val;
+ switch (p->status.stack_pointer) {
+ case 0x0:
+ p->dbg1.pc_stack_ovflw_undrn_err = 1;
+ rc = pore_handleErrEvent(p, 2, PORE_ERR_STACK_UNDERFLOW);
+ if (rc < 0)
+ return rc;
+
+ case 0x1:
+ case 0x2:
+ case 0x4:
+ next_pc->val = pc_stack0.pc_stack;
+ pc_stack0.pc_stack = p->pc_stack[1].pc_stack;
+ pore_stack0_reg_write(p, pc_stack0.val, PORE_BITS_0_63);
+ p->pc_stack[1].pc_stack = p->pc_stack[2].pc_stack;
+ p->status.stack_pointer = p->status.stack_pointer >> 1;
+ break;
+ default:
+ return PORE_ERR_INVALID_STACK_POINTER;
+ }
+
+ return PORE_SUCCESS;
+}
+
+/* Error handling ************************************************************/
+
+/// Take Action Based on Error event and Error Mask setting. If PORE
+/// is programmed to stop on the error and d_errorBreak is true (the
+/// default), we break simulation.
+
+static void signalError(pore_model_t p)
+{
+ dprintf(p, "%s()\n", __func__);
+
+ if (!p->errorCallback)
+ return;
+ p->errorCallback(p);
+}
+
+static void signalFatalError(pore_model_t p)
+{
+ dprintf(p, "%s()\n", __func__);
+
+ if (!p->fatalErrorCallback)
+ return;
+ return p->fatalErrorCallback(p);
+}
+
+/**
+ * Error event 0: During instruction execution phase, a non-zero
+ * return code was received from PORE's pervasive PIB Master interface
+ * or parity error detected in PIB read data. The SBE will also use
+ * this error event in case of a Fast I2C protocol hang (poll count
+ * for SEEPROM/Flash/OTPROM access completion reached threshold as
+ * defined in). If error mask register bit20 is set, then the
+ * return-code chiplet offline (0b010) does not trigger this error
+ * event.
+ *
+ * Error event 1: During instruction execution phase, a non-zero
+ * return code was received from PORE's OCI Master interface or parity
+ * error detected in OCI read data (PORE_SBE has a pervasive PIB
+ * Master IF only. So this error event is unused.)
+ *
+ * Error event 2: Error during instruction fetching or decode, which
+ * is either:
+ * - bad instruction parity, if instruction parity checking is enabled
+ * - invalid instruction code
+ * - invalid start vector (SV) trigger
+ * - invalid instruction path (I2CM parameter miss)
+ * - invalid instruction operand (any other register selected than
+ * documented in (Table 4.8))
+ * - instruction counter (PC) overflow or underrun in relative addressing
+ * - PC stack overflow/underrun: BSR/BSRD to a full stack/RET on empty stack
+ * - instruction fetching error: a non-zero return-code was received
+ * during instruction fetching (single for short instruction or up to
+ * three times for long operations)
+ * - SBE only: Fast I2C protocol hang (poll count for SEEPROM/Flash/OTPROM
+ * access completion reached threshold during an instruction fetch).
+ *
+ * Each error cause is indicated by a corresponding bit in DBG
+ * Register1. Since errors on this event are fatal for PORE, it is
+ * highly recommended to configure the actions �Stop IBUF execution
+ * and IBUF fatal error in the IBUF Error Mask register. This is
+ * the default setting.
+ *
+ * Error event 3: Internal data error during instruction execution:
+ * Detected bad data consistency checking, e.g. bad scan-data CRC
+ *
+ * Error event 4: Error-on-Error. Any error occurred when DBG Regs0-1
+ * are already locked: DBG_Reg1(63) = 1.
+ *
+ * Error events 2 and 3 will always freeze the DBG registers while
+ * error event 0 and 1 will only freeze the DBG registers if the
+ * corresponding Error Handler is enabled in the Error_Mask register.
+ */
+int
+pore_handleErrEvent(pore_model_t p, int error_in, int model_err)
+{
+ int me;
+ int error = error_in;
+
+ // Check for error on error. If yes change to err event
+ // 4. Else lock the debug registers for events 2, 3 and
+ // 0, 1 only if err_handler is enabled.
+
+ if (p->dbg1.debug_regs_locked == 1)
+ error = 4;
+
+ switch (error) {
+ case 0:
+ if ((p->error_mask.enable_err_output0 == 0) &&
+ (p->error_mask.enable_fatal_error0 == 0) &&
+ (p->error_mask.stop_exe_on_error0 == 0) &&
+ (p->error_mask.enable_err_handler0 == 0))
+ return PORE_ERROR_IGNORED;
+
+ if (p->error_mask.enable_err_output0)
+ signalError(p);
+ if (p->error_mask.enable_fatal_error0)
+ signalFatalError(p);
+ if (p->error_mask.stop_exe_on_error0) {
+ p->control.start_stop = 1;
+ }
+ else if (p->error_mask.enable_err_handler0) {
+ p->dbg1.debug_regs_locked = 1;
+
+ /* push pc onto stack, only if there is space */
+ me = push(p, p->status.pc, 1);
+ if (me < 0) {
+ model_err = me;
+ break;
+ }
+ pore_errorVector(p, 0);
+ }
+ break;
+ case 1:
+ if ((p->error_mask.enable_err_output1 == 0) &&
+ (p->error_mask.enable_fatal_error1 == 0) &&
+ (p->error_mask.stop_exe_on_error1 == 0) &&
+ (p->error_mask.enable_err_handler1 == 0))
+ return PORE_ERROR_IGNORED;
+
+ if (p->error_mask.enable_err_output1)
+ signalError(p);
+ if (p->error_mask.enable_fatal_error1)
+ signalFatalError(p);
+ if (p->error_mask.stop_exe_on_error1) {
+ p->control.start_stop = 1;
+ }
+ else if (p->error_mask.enable_err_handler1) {
+ p->dbg1.debug_regs_locked = 1;
+
+ /* push pc onto stack, only if there is space */
+ me = push(p, p->status.pc, 1);
+ if (me < 0) {
+ model_err = me;
+ break;
+ }
+ pore_errorVector(p, 1);
+ }
+ break;
+ case 2:
+ p->dbg1.debug_regs_locked = 1;
+
+ if ((p->error_mask.enable_err_output2 == 0) &&
+ (p->error_mask.enable_fatal_error2 == 0) &&
+ (p->error_mask.stop_exe_on_error2 == 0) &&
+ (p->error_mask.enable_err_handler2 == 0))
+ return PORE_ERROR_IGNORED;
+
+ if (p->error_mask.enable_err_output2)
+ signalError(p);
+ if (p->error_mask.enable_fatal_error2)
+ signalFatalError(p);
+ if (p->error_mask.stop_exe_on_error2) {
+ p->control.start_stop = 1;
+ }
+ else if (p->error_mask.enable_err_handler2) {
+ /* push pc onto stack, only if there is space */
+ me = push(p, p->status.pc, 1);
+ if (me < 0) {
+ model_err = me;
+ break;
+ }
+ pore_errorVector(p, 2);
+ }
+ break;
+ case 3:
+ p->dbg1.debug_regs_locked = 1;
+
+ if ((p->error_mask.enable_err_output3 == 0) &&
+ (p->error_mask.enable_fatal_error3 == 0) &&
+ (p->error_mask.stop_exe_on_error3 == 0) &&
+ (p->error_mask.enable_err_handler3 == 0))
+ return PORE_ERROR_IGNORED;
+
+ if (p->error_mask.enable_err_output3)
+ signalError(p);
+ if (p->error_mask.enable_fatal_error3)
+ signalFatalError(p);
+ if (p->error_mask.stop_exe_on_error3) {
+ p->control.start_stop = 1;
+ }
+ else if (p->error_mask.enable_err_handler3) {
+ /* push pc onto stack, only if there is space */
+ me = push(p, p->status.pc, 1);
+ if (me < 0) {
+ model_err = me;
+ break;
+ }
+ pore_errorVector(p, 3);
+ }
+ break;
+ case 4:
+ if ((p->error_mask.enable_err_output4 == 0) &&
+ (p->error_mask.enable_fatal_error4 == 0) &&
+ (p->error_mask.stop_exe_on_error4 == 0) &&
+ (p->error_mask.enable_err_handler4 == 0))
+ return PORE_ERROR_IGNORED;
+
+ if (p->error_mask.enable_err_output4)
+ signalError(p);
+ if (p->error_mask.enable_fatal_error4)
+ signalFatalError(p);
+ if (p->error_mask.stop_exe_on_error4) {
+ p->control.start_stop = 1;
+ }
+ else if (p->error_mask.enable_err_handler4) {
+ me = push(p, p->status.pc, 1);
+ if (me < 0) {
+ model_err = me;
+ break;
+ }
+ pore_errorVector(p, 4);
+ }
+ break;
+ default:
+ return PORE_ERR_NOT_IMPLEMENTED;
+ }
+ return model_err;
+}
+
+/* External register encodings ***********************************************/
+
+uint64_t pore_readReg(pore_model_t p, pore_reg_t reg, uint64_t msk)
+{
+ uint64_t val;
+
+ switch (reg) {
+ case PORE_R_STATUS: val = p->status.val; break;
+ case PORE_R_CONTROL: val = p->control.val; break;
+ case PORE_R_RESET: val = p->reset.val; break;
+ case PORE_R_ERROR_MASK: val = p->error_mask.val; break;
+ case PORE_R_PRV_BASE_ADDR0: val = p->prv_base[0].val; break;
+ case PORE_R_PRV_BASE_ADDR1: val = p->prv_base[1].val; break;
+ case PORE_R_OCI_MEMORY_BASE_ADDR0: val = p->oci_base[0].val; break;
+ case PORE_R_OCI_MEMORY_BASE_ADDR1: val = p->oci_base[1].val; break;
+ case PORE_R_TABLE_BASE_ADDR: val = p->table_base_addr.val; break;
+ case PORE_R_EXE_TRIGGER: val = p->exe_trigger.val; break;
+ case PORE_R_SCRATCH0: val = p->scratch0.val; break;
+ case PORE_R_SCRATCH1: val = p->scratch1; break;
+ case PORE_R_SCRATCH2: val = p->scratch2; break;
+ case PORE_R_IBUF_01: val = p->ibuf_01.val; break;
+ case PORE_R_IBUF_2: val = p->ibuf_2.val; break;
+ case PORE_R_DBG0: val = p->dbg0.val; break;
+ case PORE_R_DBG1: val = p->dbg1.val; break;
+ case PORE_R_PC_STACK0: val = p->pc_stack[0].val; break;
+ case PORE_R_PC_STACK1: val = p->pc_stack[1].val; break;
+ case PORE_R_PC_STACK2: val = p->pc_stack[2].val; break;
+ case PORE_R_ID_FLAGS: val = p->id_flags.val; break;
+ case PORE_R_DATA0: val = p->data0; break;
+ case PORE_R_MEM_RELOC: val = p->memory_reloc.val; break;
+ case PORE_R_I2C_E0_PARAM: val = p->i2c_e_param[0].val; break;
+ case PORE_R_I2C_E1_PARAM: val = p->i2c_e_param[1].val; break;
+ case PORE_R_I2C_E2_PARAM: val = p->i2c_e_param[2].val; break;
+ default:
+ eprintf(p, "%s: err: illegal reg %x\n", __func__, reg);
+ return PORE_ERR_INVALID_PARAM;
+ }
+
+ dprintf(p, "<== %s: reg=%02x val=%016llx mask=%016llx\n",
+ __func__, reg, (long long)val, (long long)msk);
+
+ return val & msk;
+}
+
+uint64_t pore_readRegRaw(pore_model_t p, pore_reg_t reg,
+ uint64_t msk __attribute__((unused)))
+{
+ return pore_readReg(p, reg, msk);
+}
+
+static void write_under_mask(uint64_t *reg, uint64_t n_val, uint64_t mask)
+{
+ uint64_t o_val = *reg;
+ *reg = ((n_val & mask) | /* new val */
+ (o_val & ~mask)); /* old val */
+}
+
+/**
+ * Writing any data to either PIBMS_DBG Reg0 or Reg1 unsets their lock
+ * and resets PIBMS_DBG1(63).
+ */
+int pore_writeReg(pore_model_t p, pore_reg_t reg, uint64_t val, uint64_t msk)
+{
+ dprintf(p, "==> %s: reg=%02x val=%016llx mask=%016llx\n",
+ __func__, reg, (long long)val, (long long)msk);
+
+ switch (reg) {
+ case PORE_R_STATUS:
+ write_under_mask(&p->status.val, val, msk);
+ break;
+ case PORE_R_CONTROL: /* SIDE EFFECTS */
+ return pore_control_reg_write(p, val, msk);
+
+ case PORE_R_RESET:
+ write_under_mask(&p->reset.val,
+ val & PORE_RESET_VALID_BITS, msk);
+ break;
+ case PORE_R_ERROR_MASK:
+ write_under_mask(&p->error_mask.val,
+ val & PORE_ERROR_MASK_VALID_BITS, msk);
+ break;
+
+ case PORE_R_PRV_BASE_ADDR0:
+ write_under_mask(&p->prv_base[0].val,
+ val & PORE_PRV_BASE_ADDRESS_VALID_BITS, msk);
+ break;
+ case PORE_R_PRV_BASE_ADDR1:
+ write_under_mask(&p->prv_base[1].val,
+ val & PORE_PRV_BASE_ADDRESS_VALID_BITS, msk);
+ break;
+
+ case PORE_R_OCI_MEMORY_BASE_ADDR0:
+ write_under_mask(&p->oci_base[0].val,
+ val & PORE_OCI_BASE_ADDRESS_VALID_BITS, msk);
+ break;
+ case PORE_R_OCI_MEMORY_BASE_ADDR1:
+ write_under_mask(&p->oci_base[1].val,
+ val & PORE_OCI_BASE_ADDRESS_VALID_BITS, msk);
+ break;
+
+ case PORE_R_TABLE_BASE_ADDR:
+ write_under_mask(&p->table_base_addr.val, val, msk);
+ break;
+ case PORE_R_EXE_TRIGGER: /* SIDE EFFECTS */
+ return pore_exe_trigger_reg_write(p, val, msk);
+ case PORE_R_SCRATCH0:
+ write_under_mask(&p->scratch0.val,
+ val & PORE_SCRATCH0_VALID_BITS, msk);
+ break;
+ case PORE_R_SCRATCH1:
+ write_under_mask(&p->scratch1, val, msk);
+ break;
+ case PORE_R_SCRATCH2:
+ write_under_mask(&p->scratch2, val, msk);
+ break;
+ case PORE_R_IBUF_01: /* SIDE EFFECTS */
+ return pore_ibuf_01_reg_write(p, val, msk);
+ case PORE_R_IBUF_2:
+ write_under_mask(&p->ibuf_2.val, val, msk);
+ break;
+ case PORE_R_DBG0:
+ p->dbg1.debug_regs_locked = 0; /* Writing will unlock */
+ write_under_mask(&p->dbg0.val, val& PORE_DBG0_VALID_BITS, msk);
+ break;
+ case PORE_R_DBG1:
+ p->dbg1.debug_regs_locked = 0; /* Writing will unlock */
+ write_under_mask(&p->dbg1.val, val& PORE_DBG1_VALID_BITS, msk);
+ break;
+ case PORE_R_PC_STACK0: /* SIDE EFFECTS */
+ return pore_stack0_reg_write(p, val, msk);
+ case PORE_R_PC_STACK1:
+ write_under_mask(&p->pc_stack[1].val,
+ val & PORE_PC_STACK1_VALID_BITS, msk);
+ break;
+ case PORE_R_PC_STACK2:
+ write_under_mask(&p->pc_stack[2].val,
+ val & PORE_PC_STACK2_VALID_BITS, msk);
+ break;
+ case PORE_R_ID_FLAGS:
+ write_under_mask(&p->id_flags.val,
+ val & PORE_ID_FLAGS_VALID_BITS, msk);
+ break;
+ case PORE_R_DATA0:
+ write_under_mask(&p->data0,
+ val & PORE_DATA0_VALID_BITS, msk);
+ break;
+ case PORE_R_MEM_RELOC:
+ write_under_mask(&p->memory_reloc.val,
+ val & PORE_MEMORY_RELOC_VALID_BITS, msk);
+ break;
+ case PORE_R_I2C_E0_PARAM:
+ write_under_mask(&p->i2c_e_param[0].val,
+ val & PORE_I2C_E0_PARAM_VALID_BITS, msk);
+ break;
+ case PORE_R_I2C_E1_PARAM:
+ write_under_mask(&p->i2c_e_param[1].val,
+ val & PORE_I2C_E1_PARAM_VALID_BITS, msk);
+ break;
+ case PORE_R_I2C_E2_PARAM:
+ write_under_mask(&p->i2c_e_param[2].val,
+ val & PORE_I2C_E2_PARAM_VALID_BITS, msk);
+ break;
+ default:
+ eprintf(p, "%s: err: illegal reg %x\n", __func__, reg);
+ return PORE_ERR_INVALID_PARAM;
+ }
+ return PORE_SUCCESS;
+}
+
+int pore_writeRegRaw(pore_model_t p, pore_reg_t reg, uint64_t val,
+ uint64_t msk)
+{
+ switch (reg) {
+ case PORE_R_CONTROL:
+ write_under_mask(&p->control.val, val, msk);
+ break;
+ case PORE_R_EXE_TRIGGER:
+ write_under_mask(&p->exe_trigger.val,
+ val & PORE_EXE_TRIGGER_VALID_BITS, msk);
+ break;
+ case PORE_R_IBUF_01:
+ write_under_mask(&p->ibuf_01.val, val, msk);
+ break;
+ case PORE_R_PC_STACK0:
+ write_under_mask(&p->pc_stack[0].val, val, msk);
+ break;
+ case PORE_R_DBG0:
+ write_under_mask(&p->dbg0.val, val& PORE_DBG0_VALID_BITS, msk);
+ break;
+ case PORE_R_DBG1:
+ write_under_mask(&p->dbg1.val, val& PORE_DBG1_VALID_BITS, msk);
+ break;
+
+ default:
+ return pore_writeReg(p, reg, val, msk);
+ }
+ return PORE_SUCCESS;
+}
+
+/*** PIB Bus with correct address translation using PORe offset regs *********/
+
+/**
+ * See Table 4.53: PRV address arithmetic.
+ */
+static int
+computeDirectPibDataAddress(pore_model_t p, uint32_t ima24,
+ uint32_t *pibAddress, int read_not_write)
+{
+ int me = 0;
+ PoreAddress address;
+ uint32_t baseSelect, localAddress, chipletId, mc, port;
+ pore_prv_base_address_reg *prv_base;
+
+ if (!p)
+ return PORE_ERR_INVALID_PARAM;
+
+ localAddress = ima24 & 0xffff;
+ port = (ima24 >> 16) & 0xf;
+ address.val = 0;
+ address.offset = localAddress << 2;
+
+ baseSelect = ima24 & 0x400000;
+ if (baseSelect) {
+ prv_base = &p->prv_base[1];
+ } else {
+ prv_base = &p->prv_base[0];
+ }
+
+ chipletId = prv_base->chiplet_id;
+ mc = prv_base->mc; /* multicast */
+ address.memorySpace = (mc << 14) | (chipletId << 8) | port;
+
+ if (pore_get_enableAddressHooks(p)) {
+ if (read_not_write) {
+ pore_readHook(p, address.val);
+ } else {
+ pore_writeHook(p, address.val);
+ }
+ }
+
+ *pibAddress = (address.memorySpace << 16) | localAddress;
+ return me;
+}
+
+int pore_pib_write(pore_model_t p, uint64_t addr, const uint8_t *buf,
+ unsigned int len, int *err_code)
+{
+ int rc;
+ struct pore_bus *pib = p->pib;
+
+ if (!pib)
+ return PORE_ERR_UNCONNECTED_BUS;
+ if (len != 8) {
+ BUG();
+ return PORE_ERR_INVALID_PARAM;
+ }
+
+ rc = poreb_write(pib, addr, buf, len, err_code);
+
+ if (p->dbg1.debug_regs_locked == 0) {
+ p->dbg0.last_completed_address = addr & 0xFFFFFFFF;
+ p->dbg0.last_ret_code_prv = *err_code;
+ }
+
+ p->id_flags.pib_status = *err_code;
+ p->id_flags.pib_parity_fail = 0;
+
+ pib_printf(p, " putScom: addr=%016llx data=%016llx err_code=%x\n",
+ (long long)addr, *(long long *)buf, *err_code);
+
+ return rc;
+}
+
+int pore_pib_read(pore_model_t p, uint64_t addr, uint8_t *buf,
+ unsigned int len, int *err_code)
+{
+ int rc;
+ struct pore_bus *pib = p->pib;
+
+ if (!pib)
+ return PORE_ERR_UNCONNECTED_BUS;
+ if (len != 8) {
+ BUG();
+ return PORE_ERR_INVALID_PARAM;
+ }
+
+ rc = poreb_read(pib, addr, buf, len, err_code);
+ if (p->dbg1.debug_regs_locked == 0) {
+ p->dbg0.last_completed_address = addr & 0xFFFFFFFF;
+ p->dbg0.last_ret_code_prv = *err_code;
+ }
+
+ p->id_flags.pib_status = *err_code;
+ p->id_flags.pib_parity_fail = 0;
+
+ pib_printf(p, " getScom: addr=%016llx data=%016llx err_code=%x\n",
+ (long long)addr, *(long long *)buf, *err_code);
+
+ return rc;
+}
+
+/// Fetch an instruction word using PIB direct addressing. This is
+/// somewhat analogous to the OCI fetch buffer case in that we fetch 8
+/// bytes but only return 4, however for some reason they don't buffer
+/// PIB fetches.
+
+static int
+fetchInstructionWordPibDirect(pore_model_t p, PoreAddress *pc,
+ uint32_t *word, int *err_code)
+{
+ int rc = 0;
+ uint64_t data;
+ uint32_t offset = pc->offset;
+ uint32_t pibAddress = (pc->memorySpace << 16) | (offset >> 3);
+ struct pore_bus *pib = p->pib;
+
+ if (!pib)
+ return PORE_ERR_UNCONNECTED_BUS;
+
+ /* always fetch 8 byte on the PIB */
+ rc = poreb_read(pib, pibAddress, (uint8_t *)&data, sizeof(data),
+ err_code);
+
+ if (p->dbg1.debug_regs_locked == 0) {
+ p->dbg0.last_completed_address = pibAddress & 0xFFFFFFFF;
+ p->dbg0.last_ret_code_prv = *err_code;
+ }
+
+ p->id_flags.pib_status = *err_code;
+ p->id_flags.pib_parity_fail = 0;
+
+ pib_printf(p, " getScom: addr=%016llx data=%016llx err_code=%x\n",
+ (long long)pibAddress, (long long)data, *err_code);
+
+ if (rc != sizeof(data)) {
+ return PORE_ERR_FETCH;
+ }
+
+ *word = ((offset & 0x7) == 0) ? data >> 32 : data & 0xffffffff;
+ return rc;
+}
+
+static int pore_pib_fetch(pore_model_t p, uint64_t _pc,
+ uint64_t *ibuf_01,
+ uint64_t *ibuf_2,
+ unsigned int *size,
+ int *err_code)
+{
+ int me;
+ uint32_t i_word;
+ PoreAddress pc;
+
+ *ibuf_01 = *ibuf_2 = 0;
+ pc.val = _pc;
+ me = fetchInstructionWordPibDirect(p, &pc, &i_word, err_code);
+ if (me < 0)
+ return me;
+
+ *ibuf_01 = (uint64_t)i_word << 32;
+ *size = 4;
+ if (i_word & 0x80000000) {
+ pc.offset += 4;
+ me = fetchInstructionWordPibDirect(p, &pc, &i_word, err_code);
+ if (me < 0)
+ return me;
+ *size += 4;
+ *ibuf_01 |= i_word;
+ pc.offset += 4;
+ me = fetchInstructionWordPibDirect(p, &pc, &i_word, err_code);
+ if (me < 0)
+ return me;
+ *size += 4;
+ *ibuf_2 = (uint64_t)i_word << 32;
+ }
+ return PORE_SUCCESS;
+}
+
+/*****************************************************************************/
+
+/// The Instruction Fetch Routine
+///
+/// This function computes the effective address and fetches the
+/// instructions from the fetch buffer to IBUF.
+
+static int fetch(pore_model_t p)
+{
+ int rc;
+ int recursion_stop = 0;
+
+ redo_fetch:
+ if (recursion_stop == 2)
+ return PORE_ERR_INVALID_PARAM; /* STOP calling myself */
+
+ if (!p)
+ return PORE_ERR_INVALID_PARAM;
+
+ if (p->enableAddressHooks && p->fetchHook) {
+ int _rc;
+
+ /* FIXME There is some more done in the existing model
+ * e.g. setting forchedBranchMode ... Need to
+ * understand it before I will reintegrate.
+ */
+ p->forcedBranch = 0;
+ p->forcedBranchMode = FORCED_BRANCH_FETCH_HOOK;
+ _rc = pore_fetchHook(p, p->status.pc);
+ p->forcedBranchMode = FORCED_BRANCH_DISALLOWED;
+
+ /* Model was modified from outside!!! */
+ if (!_rc) {
+ if (p->forcedBranch) {
+ p->status.pc = p->forcedPc;
+ recursion_stop++;
+ goto redo_fetch;
+ }
+ }
+ }
+
+ /* zero the input buffers, such that we see 0s even on errors */
+ p->ibuf_01.val = 0;
+ p->ibuf_2.val = 0;
+
+ if (p->status.pc & 0x0000800000000000ull) {
+ rc = poreb_fetch(p->mem, p->status.pc,
+ &p->ibuf_01.val, &p->ibuf_2.val,
+ &p->opcode_len, &p->err_code);
+ } else {
+ rc = pore_pib_fetch(p, p->status.pc,
+ &p->ibuf_01.val, &p->ibuf_2.val,
+ &p->opcode_len, &p->err_code);
+
+ /* Error occured during transaction try to handle it */
+ if ((rc < 0) && (p->id_flags.pib_status != PORE_PCB_SUCCESS)) {
+ dprintf(p, "PCB ERROR %x occured\n",
+ (unsigned int)p->id_flags.pib_status);
+
+ if ((p->id_flags.pib_status != PORE_PCB_CHIPLET_OFFLINE) ||
+ (p->error_mask.gate_chiplet_offline_err == 0)) {
+ rc = pore_handleErrEvent(p, 2, rc);
+ } else {
+ /* HW190098: PORE Model not handling
+ mask of offline cores correctly */
+ rc = PORE_SUCCESS;
+ }
+ }
+ }
+
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.pc_last_access = p->status.pc;
+ if (rc < 0) {
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.instruction_fetch_error = 1;
+ rc = pore_handleErrEvent(p, 2, rc);
+ return rc;
+ }
+ return rc;
+}
+
+static int decode(pore_model_t p)
+{
+ uint32_t *q;
+ PoreInlineDecode *dis;
+
+ if (!p)
+ return PORE_ERR_INVALID_PARAM;
+
+ dis = &p->dis;
+ pore_inline_decode_instruction(dis, p->ibuf_01.ibuf0);
+ pore_inline_decode_imd64(dis, ((uint64_t)p->ibuf_01.ibuf1 << 32 |
+ (uint64_t)p->ibuf_2.ibuf2));
+
+ p->opcode_len = 4;
+ if (dis->long_instruction)
+ p->opcode_len = 12;
+
+ if (p->decodeHook) {
+ unsigned int i;
+ uint8_t instr[12];
+
+ /* data was temporarily turned into the host format */
+ q = (uint32_t *)instr;
+ q[0] = htobe32(p->ibuf_01.ibuf0);
+ q[1] = htobe32(p->ibuf_01.ibuf1);
+ q[2] = htobe32(p->ibuf_2.ibuf2);
+
+ dprintf(p, " IBUF[0..2]=");
+ for (i = 0; i < p->opcode_len; i++)
+ dprintf(p, "%02x", instr[i]);
+
+ dprintf(p, "\n"
+ " STAT %016llx CONT %016llx\n"
+ " D0 %016llx D1 %016llx CTR %016llx\n"
+ " P0 %016llx P1 %016llx EMR %016llx\n"
+ " A0 %016llx A1 %016llx ETR %016llx\n"
+ " I2C0 %016llx I2C0 %016llx I2C0 %016llx\n"
+ " DBG0 %016llx DBG1 %016llx\n",
+ (long long)p->status.val,
+ (long long)p->control.val,
+
+ (long long)p->scratch1,
+ (long long)p->scratch2,
+ (long long)p->scratch0.val,
+
+ (long long)p->prv_base[0].val,
+ (long long)p->prv_base[1].val,
+ (long long)p->error_mask.val,
+
+ (long long)p->oci_base[0].val,
+ (long long)p->oci_base[1].val,
+ (long long)p->exe_trigger.val,
+
+ (long long)p->i2c_e_param[0].val,
+ (long long)p->i2c_e_param[1].val,
+ (long long)p->i2c_e_param[2].val,
+
+ (long long)p->dbg0.val,
+ (long long)p->dbg1.val);
+
+ pore_decodeHook(p, instr, p->opcode_len);
+ }
+ return 0;
+}
+
+static int inExeInterfaceWrite(pore_model_t p, uint64_t write_data)
+{
+ int rc;
+ PoreInlineDecode *dis = &p->dis;
+ uint32_t addr_space, pib_addr;
+ PoreAddress address;
+ uint64_t addr = dis->ima24;
+
+ /* OCI/MEM Address Space *********************************************/
+ addr_space = addr & 0x800000;
+ if (addr_space) {
+ address.val = 0;
+ computeOciDataAddress(p, addr & 0xFFFFFF, &address, 0);
+ rc = poreb_write(p->mem, address.val, (uint8_t *)&write_data,
+ sizeof(write_data), &p->err_code);
+
+ if (p->dbg1.debug_regs_locked == 0) {
+ p->dbg1.oci_master_rd_parity_err = 0;
+ p->dbg1.last_ret_code_oci = p->err_code;
+ }
+ mem_printf(p, " putMem: addr=%016llx data=%016llx "
+ "err_code=%x\n", (long long)address.val,
+ (long long)write_data, p->err_code);
+
+ if (rc == sizeof(write_data))
+ return PORE_SUCCESS;
+
+ rc = pore_handleErrEvent(p, 2, rc);
+ return rc;
+ }
+
+ /* PIB Address Space *************************************************/
+ address.val = 0;
+ computeDirectPibDataAddress(p, addr, &pib_addr, 0);
+ rc = pore_pib_write(p, pib_addr, (uint8_t *)&write_data,
+ sizeof(write_data), &p->err_code);
+ if (rc == sizeof(write_data))
+ rc = PORE_SUCCESS;
+
+ /* Error occured during transaction try to handle it */
+ if ((rc < 0) && (p->id_flags.pib_status != PORE_PCB_SUCCESS)) {
+ if ((p->id_flags.pib_status != PORE_PCB_CHIPLET_OFFLINE) ||
+ (p->error_mask.gate_chiplet_offline_err == 0)) {
+
+ rc = pore_handleErrEvent(p, 0, rc);
+ } else {
+ /* HW190098: PORE Model not handling mask of
+ offline cores correctly */
+ rc = PORE_SUCCESS;
+ }
+ }
+ return rc;
+}
+
+static int inExeInterfaceRead(pore_model_t p, uint64_t *read_data)
+{
+ int rc;
+ PoreInlineDecode *dis = &p->dis;
+ uint32_t addr_space, pib_addr;
+ PoreAddress address;
+ uint64_t addr = dis->ima24;
+
+ *read_data = 0;
+
+ /* OCI/MEM Address Space *********************************************/
+ addr_space = addr & 0x800000;
+ if (addr_space) {
+ address.val = 0;
+ computeOciDataAddress(p, addr & 0xFFFFFF, &address, 1);
+ rc = poreb_read(p->mem, address.val, (uint8_t *)read_data,
+ sizeof(*read_data), &p->err_code);
+
+ if (p->dbg1.debug_regs_locked == 0) {
+ p->dbg1.oci_master_rd_parity_err = 0;
+ p->dbg1.last_ret_code_oci = p->err_code;
+ }
+
+ mem_printf(p, " getMem: addr=%016llx data=%016llx "
+ "err_code=%x\n", (long long)address.val,
+ (long long)*read_data, p->err_code);
+
+ if (rc == sizeof(*read_data))
+ return PORE_SUCCESS;
+
+ rc = pore_handleErrEvent(p, 2, rc);
+ return rc;
+ }
+
+ /* PIB Address Space *************************************************/
+ address.val = 0;
+ computeDirectPibDataAddress(p, addr, &pib_addr, 1);
+ rc = pore_pib_read(p, pib_addr, (uint8_t *)read_data,
+ sizeof(*read_data), &p->err_code);
+ if (rc == sizeof(*read_data))
+ rc = PORE_SUCCESS;
+
+ /* Error occured during transaction try to handle it */
+ if ((rc < 0) && (p->id_flags.pib_status != PORE_PCB_SUCCESS)) {
+ if ((p->id_flags.pib_status != PORE_PCB_CHIPLET_OFFLINE) ||
+ (p->error_mask.gate_chiplet_offline_err == 0)) {
+ rc = pore_handleErrEvent(p, 0, rc);
+ } else {
+ /* HW190098: PORE Model not handling mask of
+ offline cores correctly */
+ rc = PORE_SUCCESS;
+ }
+ }
+ return rc;
+}
+
+
+/**
+ * Example how to do scan a chain via the FSI Scan engine.
+ *
+ * General approach:
+ *
+ * 1. Write the length of the scan chain to be shifted (in this case
+ * '1') and the control bits into the Front End Length Register
+ * putcfam pu 0c02 00000001
+ *
+ * you might also want to set bit2 (setpulse) or bit4 (header check)
+ * ... but that depends.
+ *
+ * 2. Setup the Command Register with the address of the scan chain
+ * and the desired operation
+ *
+ * Now it gets a little more tricky: Bit 0 of the Command Register is
+ * a write/not_read bit. We will take the write case. The following
+ * 31 bits is the address of the scan chain.
+ *
+ * There are three easy ways to find that:
+ * - CRONUS: do a getringdump to that ring, and see what is in
+ * 0c01 => getcfam pu 0c01
+ * - CRONUS: do a getringdump pu RINGNAME -debug5.15.f and check
+ * for the mentioned address take a look at the scandef
+ *
+ * 3. Write to the FIFO with the scan info.
+ * putcfam pu 0c00 00000000
+ *
+ * Repeat step 3. for the length of the scan chain ( => length/32 times ).
+ *
+ * 4. Check the status (not mandatory :-) )
+ * getcfam pu 0c07
+ *
+ * Example: Scan of ex_dpll_gptr chain on P7
+ *
+ * # scan in
+ * putcfam pu 0c02 00000147
+ * putcfam pu 0c01 88030402
+ *
+ * putcfam pu 0c00 DEADBEEF
+ * putcfam pu 0c00 00000000
+ * putcfam pu 0c00 00000000
+ * putcfam pu 0c00 00000000
+ * putcfam pu 0c00 00000000
+ * putcfam pu 0c00 00000000
+ * putcfam pu 0c00 00000000
+ * putcfam pu 0c00 00000000
+ * putcfam pu 0c00 00000000
+ * putcfam pu 0c00 00000000
+ * putcfam pu 0c00 00000000
+ *
+ * # scan out
+ * putcfam pu 0c02 00000147
+ * putcfam pu 0c01 08030402
+ *
+ * getcfam pu 0c00
+ * getcfam pu 0c00
+ * getcfam pu 0c00
+ * getcfam pu 0c00
+ * getcfam pu 0c00
+ * getcfam pu 0c00
+ * getcfam pu 0c00
+ * getcfam pu 0c00
+ * getcfam pu 0c00
+ * getcfam pu 0c00
+ * getcfam pu 0c00
+ *
+ * Here and example doing the scan via SCOM commands:
+ * 1.) Configure Clock Control of respective chiplet
+ * 2.) Write data packets
+ *
+ * Example of EN_LBST Chain with manual 'Headercheck' (DEADBEEF as Header)
+ *
+ * en_lbst_scan
+ * putscom pu 03030007 5E000800
+ *
+ * putscom pu 03038020 deadbeef
+ * putscom pu 03038020 11112222
+ * putscom pu 03038020 33334444
+ * putscom pu 03038020 55556666
+ * putscom pu 03038020 77778888
+ * putscom pu 03038020 9999aaaa
+ * putscom pu 03038020 bbbbcccc
+ * putscom pu 03038020 ddddeeee
+ * putscom pu 03038020 ffff1212
+ * putscom pu 03038020 23233434
+ * putscom pu 03038020 FE000000
+ * putscom pu 03038020 23233434
+ * putscom pu 03038020 23233434
+ * putscom pu 03038020 23233434
+ * putscom pu 03038020 23233434
+ * putscom pu 0303801C 23233434
+ *
+ * echo "HEADERCHECK:"
+ * getscom pu 03038000
+ *
+ * putscom pu 03038020 deadbeef
+ * getscom pu 03038000
+ * getscom pu 03038020
+ * getscom pu 03038020
+ * getscom pu 03038020
+ * getscom pu 03038020
+ * getscom pu 03038020
+ * getscom pu 03038020
+ * getscom pu 03038020
+ * getscom pu 03038020
+ * getscom pu 03038020
+ * getscom pu 03038020
+ * getscom pu 03038020
+ * getscom pu 03038020
+ * getscom pu 03038020
+ * getscom pu 03038020
+ * getscom pu 0303801C
+ *
+ * Binary to Unary Translation of scan_sel:
+ * WHEN 11 scantype_allf => result := "1101.1100.1110.0000";
+ * WHEN 12 scantype_ccvf => result := "0010.1000.0000.0000";
+ * WHEN 13 scantype_lbcm => result := "0000.1000.0010.0000";
+ * WHEN 14 scantype_abfa => result := "0000.0100.0100.0000";
+ * WHEN 15 scantype_fure => result := "1001.0000.0000.0000";
+ */
+static const uint16_t bin_2_unary[] = {
+ /* unary binary */
+ 0x8000, /* 0x0 0 */
+ 0x4000, /* 0x1 1 */
+ 0x2000, /* 0x2 2 */
+ 0x1000, /* 0x3 3 */
+ 0x0800, /* 0x4 4 */
+ 0x0400, /* 0x5 5 */
+ 0x0200, /* 0x6 6 */
+ 0x0100, /* 0x7 7 */
+ 0x0080, /* 0x8 8 */
+ 0x0040, /* 0x9 9 */
+ 0x0020, /* 0xa 10 */
+ 0xdce0, /* 0xb 11 */
+ 0x2800, /* 0xc 12 */
+ 0x0820, /* 0xd 13 */
+ 0x0440, /* 0xe 14 */
+ 0x9000, /* 0xf 15 */
+};
+
+static int pore_scand_read(pore_model_t p, PoreAddress *addr, uint32_t *word)
+
+{
+ int rc;
+ uint64_t data;
+
+ if (addr->val & 0x0000800000000000ull) {
+ uint64_t memAddress;
+
+ memAddress = addr->val;
+ pore_relocateAddress(p, &memAddress);
+ rc = poreb_read(p->mem, memAddress, (uint8_t *)word,
+ sizeof(*word), &p->err_code);
+
+ if (p->dbg1.debug_regs_locked == 0) {
+ p->dbg1.oci_master_rd_parity_err = 0;
+ p->dbg1.last_ret_code_oci = p->err_code;
+ }
+
+ mem_printf(p, " getMem: addr=%016llx data=%016llx "
+ "err_code=%x\n", (long long)memAddress,
+ (long long)*word, p->err_code);
+
+ if (rc != sizeof(*word))
+ return rc;
+
+ } else {
+ uint32_t pibAddress = ((addr->memorySpace << 16) |
+ (addr->offset >> 3));
+
+ /* always read 8 byte on the PIB */
+ rc = poreb_read(p->pib, pibAddress, (uint8_t *)&data,
+ sizeof(data), &p->err_code);
+
+ if (p->dbg1.debug_regs_locked == 0) {
+ p->dbg0.last_completed_address = pibAddress;
+ p->dbg0.last_ret_code_prv = p->err_code;
+ }
+
+ mem_printf(p, " getScom: addr=%016llx data=%016llx "
+ "err_code=%x\n", (long long)pibAddress,
+ (long long)data, p->err_code);
+
+ if (rc != sizeof(data)) {
+ return rc;
+ }
+ *word = ((addr->offset & 0x7) == 0) ?
+ data >> 32 : data & 0xffffffff;
+ }
+ return PORE_SUCCESS;
+}
+
+static int pore_scand(pore_model_t p)
+{
+ int bits, rem, rc;
+ PoreInlineDecode *dis = &p->dis;
+ pore_scratch0_reg *scr0 = &p->scratch0;
+ uint32_t scan_data = 0, crc32_data = 0;
+ uint64_t write_data;
+ PoreAddress addr;
+ PibAddress pib_addr;
+ shift_eng_cmd_reg scan_sel;
+ scan_type_select_reg scan_type_sel;
+
+ pib_addr.val = 0;
+ scan_sel.val = dis->scan_select;
+
+ addr.val = p->status.pc;
+ addr.offset += dis->scan_offset * 4;
+
+ /**
+ * Setup scan region register to select correct chains,
+ * e.g. write scom 0x02030007 0x0100000800000000 (chiplet 2,
+ * non-vital region 3, type bndy)
+ */
+ pib_addr.mc = scan_sel.bc;
+ pib_addr.chiplet_id = scan_sel.chiplet_select;
+ pib_addr.prv_port = scan_sel.port;
+ pib_addr.local_addr = SCAN_REGION_OFFSET;
+
+ scan_type_sel.val = 0;
+ scan_type_sel.region_select = scan_sel.region_select;
+ scan_type_sel.type_sel_unary = bin_2_unary[scan_sel.type_sel_bin];
+ write_data = scan_type_sel.val;
+
+ rc = pore_pib_write(p, pib_addr.val, (uint8_t *)&write_data,
+ sizeof(write_data), &p->err_code);
+ if (rc < 0)
+ return rc;
+
+ for (bits = 0, rem = dis->scan_length,
+ scr0->scratch0 = dis->scan_length / 32;
+ bits < dis->scan_length;
+ bits += 32, rem -= 32,
+ scr0->scratch0--) {
+
+ int num_bits = rem > 32 ? 32 : rem;
+
+ rc = pore_scand_read(p, &addr, &scan_data);
+ if (rc < 0)
+ return rc;
+
+ /**
+ * Send PCB scan packets which have the following
+ * layout:
+ * Address is 0x0<chiplet_id>0x0380<num_bits>
+ * Data is the left aligned values to get scanned in
+ * (up to 32 bit).
+ *
+ * The last scan packet should have the updateDR bit
+ * set in the address, i.e. 0x03A0 instead of 0x380.
+ *
+ * This will clear the scan region register if scan
+ * protection is active (default). E.g. write scom
+ * 0x02038020 0xFFFFFFFF00000000 (scan 32 bit in
+ * chiplet 2, all '1')).
+ *
+ * cDR: See JTAG standard, capture data from scanlatch
+ * uDR: " update data to scanlatch
+ * Is used for PLL settings.
+ */
+
+ if (scr0->scratch0 == dis->scan_length / 32) {
+ /* Need to set cDR on 1st data access */
+ pib_addr.local_addr =
+ SCAN_DATA_OFFSET(dis->capture, 0, num_bits);
+
+ } else if (scr0->scratch0 == 0) {
+ /* Need to set uDR on last data access */
+ pib_addr.local_addr =
+ SCAN_DATA_OFFSET(0, dis->update, num_bits);
+ } else {
+ pib_addr.local_addr =
+ SCAN_DATA_OFFSET(0, 0, num_bits);
+ }
+
+ write_data = (uint64_t)scan_data << 32;
+ rc = pore_pib_write(p, pib_addr.val, (uint8_t *)&write_data,
+ sizeof(write_data), &p->err_code);
+ if (rc < 0)
+ return rc;
+
+ addr.offset += 4;
+ }
+ rc = pore_scand_read(p, &addr, &crc32_data);
+ if (rc < 0)
+ return rc;
+ p->scratch1 = crc32_data;
+
+ return PORE_SUCCESS;
+}
+
+static int execute(pore_model_t p)
+{
+ int me = PORE_SUCCESS;
+ int next_state = PORE_STATE_EXEC;
+ int trapBreakpoint = 0;
+ int addressBreakpoint = 0;
+ PoreInlineDecode *dis;
+ uint64_t write_data, read_data = 0;
+ int64_t op1, op2;
+ PoreAddress next_pc;
+
+ if (!p)
+ return PORE_ERR_INVALID_PARAM;
+
+ dis = &p->dis;
+ next_pc.val = p->status.pc;
+ p->branchTaken = 0;
+
+ switch (dis->opcode) {
+
+ case PORE_OPCODE_NOP:
+ break;
+
+ case PORE_OPCODE_TRAP:
+ // PORE hardware trap leaves the machine in the
+ // address breakpoint state.
+ if (p->control.trap_enable) {
+ trapBreakpoint = 1;
+ next_state = PORE_STATE_ABR;
+ }
+ break;
+
+ case PORE_OPCODE_HOOK:
+ if (p->enableHookInstruction) {
+ int _rc;
+
+ p->forcedBranch = 0;
+ p->forcedBranchMode = FORCED_BRANCH_HOOK_INSTRUCTION;
+ _rc = pore_instrHook(p, p->status.pc, dis->imd24,
+ dis->imd64);
+ p->forcedBranchMode = FORCED_BRANCH_DISALLOWED;
+ if (_rc) {
+ me = PORE_ERR_HOOK_FAILED;
+ break;
+ }
+ if (p->forcedBranch) {
+ next_pc.val = p->forcedPc;
+ p->branchTaken = 1;
+ }
+ }
+ break;
+
+ case PORE_OPCODE_WAIT:
+ if (p->dis.imd24 == 0) {
+ // Invalidate fetch buffer for OCI access
+ /// \bug Buffer is invalidated on reset
+ p->oci_fetchBufferValid = 0;
+ p->oci_fetchBufferCursor = 0;
+ p->oci_fetchBuffer = 0;
+
+ // This is the stop command. Raise the
+ // pore_stopped signal
+ p->control.start_stop = 1;
+
+ //unlockRegisters();
+ p->control.lock_exe_trig = 0;
+ }
+ pore_waitCallback(p, dis->imd24);
+ break;
+
+ /* Branch Instructions */
+ case PORE_OPCODE_BRA:
+ p->branchTaken = 1;
+ setJmpTarget(dis->impco24, &next_pc);
+ break;
+
+ case PORE_OPCODE_BRAD:
+ if (dis->tR != PORE_SCRATCH1_ENC &&
+ dis->tR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+ p->branchTaken = 1;
+ next_pc.val = __readReg(p, (pore_internal_reg_t)dis->tR);
+ break;
+
+ case PORE_OPCODE_BRAZ:
+ if (dis->tR != PORE_SCRATCH0_ENC &&
+ dis->tR != PORE_SCRATCH1_ENC &&
+ dis->tR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+ if (__readReg(p, (pore_internal_reg_t)dis->tR) == 0) {
+ p->branchTaken = 1;
+ setJmpTarget(dis->impco20, &next_pc);
+ }
+ break;
+
+ case PORE_OPCODE_BRANZ:
+ if (dis->tR != PORE_SCRATCH0_ENC &&
+ dis->tR != PORE_SCRATCH1_ENC &&
+ dis->tR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+ if (__readReg(p, (pore_internal_reg_t)dis->tR) != 0) {
+ p->branchTaken = 1;
+ setJmpTarget(dis->impco20, &next_pc);
+ }
+ break;
+
+ case PORE_OPCODE_BRAI:
+ p->branchTaken = 1;
+ next_pc.val = dis->impc48;
+ break;
+
+ case PORE_OPCODE_BSR:
+ me = push(p, p->status.pc + 4, 0);
+ if (me < 0) {
+ break;
+ }
+
+ p->branchTaken = 1;
+ setJmpTarget(dis->impco24 , &next_pc);
+ break;
+
+ case PORE_OPCODE_BSRD:
+ if (dis->tR != PORE_SCRATCH1_ENC &&
+ dis->tR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+ me = push(p, p->status.pc + 4, 0);
+ if (me < 0)
+ break;
+
+ p->branchTaken = 1;
+ next_pc.val = __readReg(p, (pore_internal_reg_t)dis->tR);
+ break;
+
+ case PORE_OPCODE_RET:
+ me = pop(p, &next_pc);
+ if (me < 0)
+ break;
+
+ p->branchTaken = 1;
+ break;
+
+ case PORE_OPCODE_CMPBRA:
+ if (p->scratch1 == dis->imd64) {
+ p->branchTaken = 1;
+ setJmpTarget(dis->impco24, &next_pc);
+ }
+ break;
+
+ case PORE_OPCODE_CMPNBRA:
+ if (p->scratch1 != dis->imd64) {
+ p->branchTaken = 1;
+ setJmpTarget(dis->impco24, &next_pc);
+ }
+ break;
+
+ case PORE_OPCODE_CMPBSR:
+ if (p->scratch1 == dis->imd64) {
+ me = push(p, p->status.pc + 12, 0);
+ if (me < 0)
+ break;
+
+ p->branchTaken = 1;
+ setJmpTarget(dis->impco24, &next_pc);
+ }
+ break;
+
+ case PORE_OPCODE_LOOP:
+ if (p->scratch0.scratch0 > 0) {
+ p->scratch0.scratch0 = p->scratch0.scratch0 - 1;
+ p->branchTaken = 1;
+ setJmpTarget(dis->impco24, &next_pc);
+ }
+ break;
+
+ /* ALU Instructions */
+ case PORE_OPCODE_ANDI:
+ if (dis->sR != PORE_SCRATCH1_ENC &&
+ dis->sR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+ if (dis->tR != PORE_SCRATCH1_ENC &&
+ dis->tR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+ __writeReg(p, (pore_internal_reg_t)dis->tR,
+ __readReg(p, (pore_internal_reg_t)
+ dis->sR) & dis->imd64);
+ break;
+
+ case PORE_OPCODE_ORI:
+ if (dis->sR != PORE_SCRATCH1_ENC &&
+ dis->sR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+ if (dis->tR != PORE_SCRATCH1_ENC &&
+ dis->tR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+ __writeReg(p, (pore_internal_reg_t)dis->tR,
+ __readReg(p, (pore_internal_reg_t)dis->sR) |
+ dis->imd64);
+ break;
+
+ case PORE_OPCODE_XORI:
+ if (dis->sR != PORE_SCRATCH1_ENC &&
+ dis->sR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+ if (dis->tR != PORE_SCRATCH1_ENC &&
+ dis->tR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+ __writeReg(p, (pore_internal_reg_t)dis->tR,
+ __readReg(p, (pore_internal_reg_t)dis->sR) ^
+ dis->imd64);
+ break;
+
+ case PORE_OPCODE_AND:
+ if (dis->tR != PORE_SCRATCH1_ENC &&
+ dis->tR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+ __writeReg(p, (pore_internal_reg_t)dis->tR,
+ p->scratch1 & p->scratch2);
+ break;
+
+ case PORE_OPCODE_OR:
+ if (dis->tR != PORE_SCRATCH1_ENC &&
+ dis->tR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+ __writeReg(p, (pore_internal_reg_t)dis->tR,
+ p->scratch1 | p->scratch2);
+ break;
+
+ case PORE_OPCODE_XOR:
+ if (dis->tR != PORE_SCRATCH1_ENC &&
+ dis->tR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+ __writeReg(p, (pore_internal_reg_t)dis->tR,
+ p->scratch1 ^ p->scratch2);
+ break;
+
+ case PORE_OPCODE_ADDI: {
+ int64_t add_result;
+
+ if (dis->tR == PORE_EXE_TRIGGER_ENC ||
+ dis->tR == PORE_ALU_IBUF_ID_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+
+ op1 = __readReg(p, (pore_internal_reg_t)dis->tR);
+ op2 = dis->imd16;
+ add_result = op1 + op2;
+
+ setAluFlags(p, op1, op2, add_result, dis->opcode);
+ __writeReg(p, (pore_internal_reg_t)dis->tR, add_result);
+ break;
+ }
+ case PORE_OPCODE_SUBI: {
+ int64_t sub_result;
+
+ if (dis->tR == PORE_EXE_TRIGGER_ENC ||
+ dis->tR == PORE_ALU_IBUF_ID_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+
+ op1 = __readReg(p, (pore_internal_reg_t)dis->tR);
+ op2 = dis->imd16;
+ op2 = ~op2 + 1;
+ sub_result = op1 + op2;
+
+ setAluFlags(p, op1, op2, sub_result, dis->opcode);
+ __writeReg(p, (pore_internal_reg_t)dis->tR, sub_result);
+ break;
+ }
+ case PORE_OPCODE_ADD: {
+ int64_t add_result;
+
+ if (dis->tR != PORE_SCRATCH1_ENC &&
+ dis->tR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+
+ op1 = p->scratch1;
+ op2 = p->scratch2;
+ add_result = op1 + op2;
+
+ setAluFlags(p, op1, op2, add_result, dis->opcode);
+ __writeReg(p, (pore_internal_reg_t)dis->tR, add_result);
+ break;
+ }
+ case PORE_OPCODE_SUB: {
+ int64_t sub_result;
+
+ if (dis->tR != PORE_SCRATCH1_ENC &&
+ dis->tR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+
+ op1 = p->scratch1;
+ op2 = p->scratch2;
+ op2 = ~op2 + 1;
+ sub_result = op1 + op2;
+ setAluFlags(p, op1, op2, sub_result, dis->opcode);
+ __writeReg(p, (pore_internal_reg_t)dis->tR, sub_result);
+ break;
+ }
+ case PORE_OPCODE_NEG: {
+ int64_t neg_result;
+
+ if (dis->sR != PORE_SCRATCH1_ENC &&
+ dis->sR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+ if (dis->tR != PORE_SCRATCH1_ENC &&
+ dis->tR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+
+ op1 = __readReg(p, (pore_internal_reg_t)dis->sR);
+ neg_result = ~op1 + 1;
+ __writeReg(p, (pore_internal_reg_t)dis->tR, neg_result);
+ break;
+ }
+ case PORE_OPCODE_COPY:
+ __writeReg(p, (pore_internal_reg_t)dis->tR,
+ __readReg(p, (pore_internal_reg_t)dis->sR));
+ break;
+
+ case PORE_OPCODE_ROL: {
+ uint16_t rmask = 0;
+ uint64_t result = 0;
+ uint64_t src = 0;
+
+ // Operand Check
+ rmask = dis->imd16;
+ if (rmask != 0x1 && rmask != 0x4 && rmask != 0x8
+ && rmask != 0x10 && rmask != 0x20 ) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+
+ } else if (
+ dis->sR != PORE_SCRATCH1_ENC &&
+ dis->sR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+
+ } else if (dis->tR != PORE_SCRATCH1_ENC &&
+ dis->tR != PORE_SCRATCH2_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+
+ } else {
+ src = __readReg(p, (pore_internal_reg_t)dis->sR);
+ result = ( src << rmask ) |
+ (((~(0xFFFFFFFFFFFFFFFFull >> rmask)) & src )
+ >> (64 - rmask));
+ }
+
+ __writeReg(p, (pore_internal_reg_t)dis->tR, result);
+ break;
+ }
+ /* Load/Store Instructions */
+ case PORE_OPCODE_LOAD20: {
+ if (dis->tR == PORE_EXE_TRIGGER_ENC ||
+ dis->tR == PORE_ALU_IBUF_ID_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+ /**
+ * ImD20 will be signed extended to 64b (on MSB side)
+ * and then truncated to the width of <tR>.
+ */
+ __writeReg(p, (pore_internal_reg_t)dis->tR, dis->imd20);
+ break;
+ }
+ case PORE_OPCODE_LOAD64:
+ if (dis->tR == PORE_PRV_BASE_ADDR0_ENC ||
+ dis->tR == PORE_PRV_BASE_ADDR1_ENC ||
+ dis->tR == PORE_EXE_TRIGGER_ENC ||
+ dis->tR == PORE_ALU_IBUF_ID_ENC) {
+ BUG();
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instruction_operand = 1;
+ me = pore_handleErrEvent(p,2,PORE_ERR_INVALID_OPERAND);
+ break;
+ }
+
+ __writeReg(p, (pore_internal_reg_t)dis->tR, dis->imd64);
+ break;
+
+ case PORE_OPCODE_SCR1RD: {
+ me = inExeInterfaceRead(p, &read_data);
+ if (me < 0)
+ break;
+ p->scratch1 = read_data;
+ break;
+ }
+ case PORE_OPCODE_SCR2RD: {
+ me = inExeInterfaceRead(p, &read_data);
+ if (me < 0)
+ break;
+ p->scratch2 = read_data;
+ break;
+ }
+ case PORE_OPCODE_SCR1RDA: {
+ // Read DATA from OCI/PRV Address Space using effective addr
+ me = inExeInterfaceRead(p, &read_data);
+ if (me < 0)
+ break;
+ // Apply imd64 AND mask
+ read_data &= dis->imd64;
+ p->scratch1 = read_data;
+ break;
+ }
+ case PORE_OPCODE_SCR2RDA: {
+ // Read DATA from OCI/PRV Address Space using effective addr
+ me = inExeInterfaceRead(p, &read_data);
+ if (me < 0)
+ break;
+ // Apply imd64 AND mask
+ read_data &= dis->imd64;
+ p->scratch2 = read_data;
+ break;
+ }
+ case PORE_OPCODE_WRI: {
+ write_data = dis->imd64;
+ // Write DATA to OCI/PRV Address Space using effective addr
+ me = inExeInterfaceWrite(p, write_data);
+ if (me < 0)
+ break;
+ break;
+ }
+ case PORE_OPCODE_BS: {
+ // Read OCI/PRV space from effective address to read_data
+ me = inExeInterfaceRead(p, &read_data);
+ if (me < 0)
+ break;
+ // Apply OR mask to read_data
+ read_data |= dis->imd64;
+ // update scratch register
+ p->scratch1 = read_data;
+ // Write the data back to effective address in OCI/PRV
+ me = inExeInterfaceWrite(p, read_data);
+ if (me < 0)
+ break;
+ break;
+ }
+ case PORE_OPCODE_BC: {
+ // Read OCI/PRV space from effective address to read_data
+ me = inExeInterfaceRead(p, &read_data);
+ if (me < 0)
+ break;
+ // Apply Inverted AND mask to read_data
+ read_data &= ~(dis->imd64);
+ // Update scratch register
+ p->scratch1 = read_data;
+ // Write the data back to effective address in OCI/PRV
+ me = inExeInterfaceWrite(p, read_data);
+ if (me < 0)
+ break;
+ break;
+ }
+ case PORE_OPCODE_SCR1WR: {
+ write_data = p->scratch1;
+ // Write DATA to OCI/PRV Address Space using effective addr
+ me = inExeInterfaceWrite(p, write_data);
+ if (me < 0)
+ break;
+ break;
+ }
+ case PORE_OPCODE_SCR2WR: {
+ write_data = p->scratch2;
+ // Write DATA to OCI/PRV Address Space using effective addr
+ me = inExeInterfaceWrite(p, write_data);
+ if (me < 0)
+ break;
+ break;
+ }
+ case PORE_OPCODE_SCAND:
+ me = pore_scand(p);
+ if (me < 0) {
+ me = pore_handleErrEvent(p, 2, me);
+ break;
+ }
+ break;
+
+ default:
+ eprintf(p, "err: Invalid Instruction Encoding: "
+ " %08x %08x %08x\n",
+ (unsigned int)p->ibuf_01.ibuf0,
+ (unsigned int)p->ibuf_01.ibuf0,
+ (unsigned int)p->ibuf_2.ibuf2);
+
+ if (p->dbg1.debug_regs_locked == 0)
+ p->dbg1.invalid_instr_code = 1;
+ me = pore_handleErrEvent(p, 2, PORE_ERR_INVALID_OPCODE);
+ break;
+ }
+
+ // Check for address, trap, magic breakpoints and single-step.
+ // Note that we do the dumps
+
+ addressBreakpoint = (p->status.pc == p->control.pc_brk_pt);
+
+ if (addressBreakpoint) {
+ pore_dump(p);
+ next_state = PORE_STATE_ABR;
+ p->broken = 1;
+ dprintf(p, "PORE Address Breakpoint @ 0x%012llx\n",
+ (long long)p->status.pc);
+ } else if (trapBreakpoint) {
+ pore_dump(p);
+ next_state = PORE_STATE_ABR;
+ p->broken = 1;
+ dprintf(p, "PORE Trap Breakpoint @ 0x%012llx\n",
+ (long long)p->status.pc);
+ }
+
+ // Branches have already updated the PC so the assignment to
+ // the PC is done here. Otherwise we increment the PC for the
+ // next step unless we're broken.
+ //
+ // In case of me < 0 the pore_handeErrEvent() function has set
+ // a new PC by jumping into the appropriate Error Vector. In
+ // this case we do not update the current PC instead it was
+ // pushed onto the stack. After the error handler has tidied
+ // up, it can jump back to the failing instruction.
+
+ if (me >= 0) {
+ if (p->branchTaken) {
+ p->status.pc = next_pc.val;
+ } else if (!p->broken) {
+ incrPc(p);
+ }
+ }
+
+ // Step mode. don't update state and don't schedule next step
+ // Condition can occur when we are hitting an error during
+ // instruction execution, e.g. a pib_read failed.
+
+ if (p->control.start_stop == 1) {
+ dprintf(p, "PORE was stopped during execution!\n");
+ p->status.cur_state = PORE_STATE_WAIT;
+
+ } else if (p->reset.fn_reset) {
+ dprintf(p, "PORE is being held in reset!\n");
+ me = PORE_ERR_IN_RESET;
+
+ } else{
+ p->status.cur_state = next_state;
+ }
+
+ return me;
+}
+
+/// If the instruction was broken, finish it.
+///
+/// If the PORE is an a 'broken' state, then we first need to update
+/// the PC by re-decoding the current instruction. Taken branches
+/// have already updated the PC.
+///
+/// The situation occurs if we have hit a breakpoint. In this case the
+/// PC has still the value of the breakpoint instruction, but needs to
+/// be updated when the user writes 1 to control.continue_step.
+
+static int finishBrokenInstruction(pore_model_t p)
+{
+ if (!p)
+ return PORE_ERR_INVALID_PARAM;
+
+ if (p->broken && !p->branchTaken) {
+ decode(p);
+ incrPc(p);
+ }
+
+ p->branchTaken = 0;
+ p->broken = 0;
+ return PORE_SUCCESS;
+}
+
+int pore_step(pore_model_t p)
+{
+ int rc = PORE_SUCCESS;
+
+ if (!p)
+ return PORE_ERR_INVALID_PARAM;
+
+ dprintf(p, "(0) ensure we are in correct state to do a step ...\n");
+ if (p->reset.fn_reset == 1) {
+ dprintf(p, " no: engine is in reset\n");
+ return PORE_IN_RESET;
+ }
+ if (p->control.start_stop == 1) {
+ dprintf(p, " no: engine is stopped\n");
+ return PORE_STOPPED;
+ }
+ if (p->status.cur_state == PORE_STATE_ABR) {
+ dprintf(p, " no: engine has hit a breakpoint\n");
+ return PORE_BREAKPOINT_HIT;
+ }
+
+ p->branchTaken = 0; /* reset internal state */
+ p->broken = 0;
+
+ dprintf(p, "(1) fetch @ %016llx ...\n", (long long)p->status.pc);
+ rc = fetch(p);
+ if (rc < 0) {
+ eprintf(p, "%s: err: fetch rc=%d\n", __func__, rc);
+ return rc;
+ }
+
+ dprintf(p, "(2) decode ...\n");
+ rc = decode(p);
+ if (rc < 0) {
+ eprintf(p, "%s: err: decode rc=%d\n", __func__, rc);
+ return rc;
+ }
+
+ dprintf(p, "(3) execute ...\n");
+ rc = execute(p);
+ if (rc < 0) {
+ eprintf(p, "%s: err: execute rc=%d\n", __func__, rc);
+ return rc;
+ }
+
+ return rc;
+}
+
+void pore_dump(pore_model_t p)
+{
+ PoreAddress a0, a1;
+ PoreAddress sp0, sp1, sp2;
+ int sp;
+ uint32_t p0, p1;
+
+ sp0.val = p->pc_stack[0].pc_stack;
+ sp1.val = p->pc_stack[1].pc_stack;
+ sp2.val = p->pc_stack[2].pc_stack;
+
+ a0.val = __readReg(p, PORE_OCI_MEMORY_BASE_ADDR0_ENC);
+ a1.val = __readReg(p, PORE_OCI_MEMORY_BASE_ADDR1_ENC);
+ p0 = __readReg(p, PORE_PRV_BASE_ADDR0_ENC);
+ p1 = __readReg(p, PORE_PRV_BASE_ADDR1_ENC);
+
+ aprintf("-------------------------------------"
+ "-------------------------------------\n"
+ "%s : PORE Id %d.\n"
+ "-------------------------------------"
+ "-------------------------------------\n"
+ " IBUF: %08llx %08x.%08x.%08x\n"
+ "-------------------------------------"
+ "-------------------------------------\n"
+ " D0 : %016llx D1 : %016llx\n"
+ " A0 : %04x:%08x A1 : %04x:%08x\n"
+ " P0 : %02x P1 : %02x\n"
+ " CTR : %06x\n"
+ "-------------------------------------"
+ "-------------------------------------\n",
+ __func__,
+ (uint32_t)(p->id_flags.ibuf_id),
+ (long long)p->status.pc,
+ p->ibuf_01.ibuf0,
+ p->ibuf_01.ibuf1,
+ p->ibuf_2.ibuf2,
+ (long long)p->scratch1,
+ (long long)p->scratch2,
+ (unsigned int)a0.memorySpace, (unsigned int)a0.offset,
+ (unsigned int)a1.memorySpace, (unsigned int)a1.offset,
+ p0, p1, (uint32_t)p->scratch0.scratch0);
+
+ sp = p->status.stack_pointer;
+ /* pore_status_reg_print(&p->status); */
+ /* pore_control_reg_print(&p->control); */
+
+ if (sp == 0) {
+ aprintf("The stack is empty\n");
+ } else {
+ aprintf("Stack Trace\n"
+ " Level 0 : %04x:%08x\n",
+ (unsigned int)sp0.memorySpace,
+ (unsigned int)sp0.offset);
+ if (sp > 0x1) {
+ aprintf(" Level 1 : %04x:%08x\n",
+ (unsigned int)sp1.memorySpace,
+ (unsigned int)sp1.offset);
+ }
+ if (sp > 0x2) {
+ aprintf(" Level 2 : %04x:%08x\n",
+ (unsigned int)sp2.memorySpace,
+ (unsigned int)sp2.offset);
+ }
+ }
+
+ aprintf("-------------------------------------"
+ "-------------------------------------\n"
+ "Last pervasive access @ %08x returned error code %d\n"
+ "-------------------------------------"
+ "-------------------------------------\n",
+ (uint32_t)p->dbg0.last_completed_address,
+ (int)p->dbg0.last_ret_code_prv);
+
+ aprintf(" PORe Registers\n"
+ " STATUS: %016llx CONTROL: %016llx\n"
+ " RESET: %016llx ERR_MASK: %016llx\n"
+ " PVR_BASE0/P0: %016llx PVR_BASE1/P1: %016llx\n"
+ " OCI_BASE0/A0: %016llx OCI_BASE1/A1: %016llx\n"
+ " TBL_BASE: %016llx EXE_TRIGGER: %016llx\n"
+ " SCR0/CTR: %016llx SCR1/D0: %016llx\n"
+ " SCR2/D1: %016llx IBUF012: %08llx.%08llx.%08llx\n"
+ " DBG0: %016llx DBG1: %016llx\n"
+ " PC_STACK0: %016llx PC_STACK1: %016llx\n"
+ " PC_STACK2: %016llx ID_FLAGS: %016llx\n"
+ " DATA0: %016llx MEM_RELOC: %016llx\n"
+ " I2C_E0: %016llx I2C_E1: %016llx\n"
+ " I2C_E2: %016llx PC: %016llx\n"
+ "-------------------------------------"
+ "-------------------------------------\n",
+ (long long)p->status.val, (long long)p->control.val,
+ (long long)p->reset.val, (long long)p->error_mask.val,
+ (long long)p->prv_base[0].val, (long long)p->prv_base[1].val,
+ (long long)p->oci_base[0].val, (long long)p->oci_base[1].val,
+ (long long)p->table_base_addr.val,
+ (long long)p->exe_trigger.val,
+ (long long)p->scratch0.val, (long long)p->scratch1,
+ (long long)p->scratch2, (long long)p->ibuf_01.ibuf0,
+ (long long)p->ibuf_01.ibuf1, (long long)p->ibuf_2.ibuf2,
+ (long long)p->dbg0.val, (long long)p->dbg1.val,
+ (long long)p->pc_stack[0].val, (long long)p->pc_stack[1].val,
+ (long long)p->pc_stack[2].val, (long long)p->id_flags.val,
+ (long long)p->data0, (long long)p->memory_reloc.val,
+ (long long)p->i2c_e_param[0].val,
+ (long long)p->i2c_e_param[1].val,
+ (long long)p->i2c_e_param[2].val,
+ (long long)p->status.pc);
+}
+
+/* Model Creation ************************************************************/
+
+int pore_flush_reset(pore_model_t p)
+{
+ dprintf(p, "%s: %s\n", __func__, p->name);
+
+ p->status.val = 0;
+ p->status.cur_state = PORE_STATE_WAIT;
+
+ p->control.val = 0;
+ p->control.start_stop = 1;
+
+ p->control.lock_exe_trig = 0;
+ p->control.check_parity = 0;
+ p->control.prv_parity = 0;
+ p->control.pc_brk_pt = 0xffffffffffffull;
+
+ p->prv_base[0].val = 0;
+ p->prv_base[1].val = 0;
+ p->oci_base[0].val = 0;
+ p->oci_base[1].val = 0;
+ p->table_base_addr.val = 0;
+ p->exe_trigger.val = 0;
+ p->scratch0.val = 0;
+ p->scratch1 = 0;
+ p->scratch2 = 0;
+ p->ibuf_01.val = 0;
+ p->ibuf_2.val = 0;
+
+ p->id_flags.val = p->id_flags.ibuf_id; /* keep ibuf_id */
+ p->dbg0.val = 0;
+ p->dbg1.val = 0;
+ p->pc_stack[0].val = 0; /* clears one bits on a write */
+ p->pc_stack[1].val = 0;
+ p->pc_stack[2].val = 0;
+
+ p->data0 = 0;
+ p->memory_reloc.val = 0;
+ p->status.pc = 0;
+ p->err_code = 0;
+ p->branchTaken = 0;
+ p->broken = 0;
+ p->singleStep = 0;
+ p->forcedBranchMode = FORCED_BRANCH_DISALLOWED;
+ p->forcedPc = 0;
+ /* page 74: IBUF Err Mask, not altered during functional PORE reset. */
+
+ poreb_reset(p->pib); /* reset bus models, e.g. clear buffers */
+ poreb_reset(p->mem);
+
+ return 0;
+}
+
+pore_model_t pore_model_create(const char *name)
+{
+ pore_model_t p;
+
+ p = (pore_model_t)malloc(sizeof(*p));
+ if (!p)
+ return NULL;
+ memset(p, 0, sizeof(*p));
+
+ p->name = name;
+ pore_flush_reset(p);
+ p->status.pc = 0;
+ p->enableHookInstruction = 0;
+ p->enableAddressHooks = 0;
+
+ p->trace_flags = PORE_TRACE_ERR;
+ return p;
+}
+
+void pore_model_destroy(pore_model_t p)
+{
+ poreb_destroy(p->pib);
+ poreb_destroy(p->mem);
+ free(p);
+}
+
+int pore_registerHooks (pore_model_t p,
+ instrHook_f instrHook,
+ readHook_f readHook,
+ writeHook_f writeHook,
+ fetchHook_f fetchHook,
+ decodeHook_f decodeHook)
+{
+ p->instrHook = instrHook;
+ p->readHook = readHook;
+ p->writeHook = writeHook;
+ p->fetchHook = fetchHook;
+ p->decodeHook = decodeHook;
+ return 0;
+}
+
+int pore_registerCallbacks(pore_model_t p,
+ waitCallback_f waitCallback,
+ errorCallback_f errorCallback,
+ errorCallback_f fatalErrorCallback)
+{
+ p->waitCallback = waitCallback;
+ p->errorCallback = errorCallback;
+ p->fatalErrorCallback = fatalErrorCallback;
+ return 0;
+}
+
+void pore_setpriv(pore_model_t p, void *priv)
+{
+ p->priv = priv;
+}
+
+void *pore_getpriv(pore_model_t p)
+{
+ return p->priv;
+}
+
+/* recursive function to setup the pore pointer in all bus attachements */
+static void poreb_set_pore(struct pore_bus *b, pore_model_t p)
+{
+ unsigned int i;
+
+ if (b == NULL)
+ return;
+ b->pore = p;
+ for (i = 0; i < PORE_MAX_BUS; i++)
+ poreb_set_pore(b->slaves[i], p);
+}
+
+int pore_attach_mem(pore_model_t p, struct pore_bus *b)
+{
+ p->mem = b;
+ poreb_set_pore(b, p);
+ return 0;
+}
+
+int pore_attach_pib(pore_model_t p, struct pore_bus *b)
+{
+ p->pib = b;
+ poreb_set_pore(b, p);
+ return 0;
+}
+
+int pore_extractState(pore_model_t p, struct pore_state *s)
+{
+ memcpy(s, p, sizeof(*s));
+ return 0;
+}
+
+int pore_installState(pore_model_t p, const struct pore_state *s)
+{
+ memcpy(p, s, sizeof(*s));
+ return 0;
+}
+
+void pore_set_enableHookInstr(pore_model_t p, int enabled)
+{
+ p->enableHookInstruction = enabled;
+}
+
+int pore_get_enableHookInstr(pore_model_t p)
+{
+ return p->enableHookInstruction;
+}
+
+void pore_set_enableAddressHooks(pore_model_t p, int enabled)
+{
+ p->enableAddressHooks = enabled;
+}
+
+int pore_get_enableAddressHooks(pore_model_t p)
+{
+ return p->enableAddressHooks;
+}
+
+int
+pore_forceBranch(pore_model_t p, uint64_t addr)
+{
+ switch (p->forcedBranchMode) {
+
+ case FORCED_BRANCH_DISALLOWED:
+ return PORE_ERR_ILLEGAL_FORCED_BRANCH;
+
+ case FORCED_BRANCH_FETCH_HOOK:
+ case FORCED_BRANCH_HOOK_INSTRUCTION:
+ p->forcedPc = addr;
+ p->forcedBranch = 1;
+ break;
+ }
+ return PORE_SUCCESS;
+}
+
+int pore_stop(pore_model_t p)
+{
+ uint64_t control;
+ control = pore_readReg(p, PORE_R_CONTROL, PORE_BITS_0_63);
+ /* set start_stop bit[0] */
+ pore_writeReg(p, PORE_R_CONTROL, control | BE64_BIT(0),
+ PORE_BITS_0_63);
+ return PORE_SUCCESS;
+}
+
+int pore_start(pore_model_t p)
+{
+ uint64_t control;
+ control = pore_readReg(p, PORE_R_CONTROL, PORE_BITS_0_63);
+ /* clear start_stop bit[0] */
+ pore_writeReg(p, PORE_R_CONTROL, control & ~BE64_BIT(0),
+ PORE_BITS_0_63);
+ return PORE_SUCCESS;
+}
+
+int pore_setPc(pore_model_t p, uint64_t pc)
+{
+ pore_stop(p);
+ pore_writeReg(p, PORE_R_CONTROL, BE64_BIT(3) |
+ (pc & BE64_MASK(16, 63)), PORE_BITS_0_63);
+ return PORE_SUCCESS;
+}
+
+int pore_setBreakpoint(pore_model_t p, uint64_t bp)
+{
+ uint64_t control;
+
+ control = pore_readReg(p, PORE_R_CONTROL, PORE_BITS_0_63);
+ control &= ~BE64_MASK(16, 63);
+ control |= (bp & BE64_MASK(16, 63));
+ pore_writeReg(p, PORE_R_CONTROL, control, PORE_BITS_0_63);
+ return PORE_SUCCESS;
+}
+
+int pore_enableTrap(pore_model_t p, int enable)
+{
+ uint64_t control;
+
+ control = pore_readReg(p, PORE_R_CONTROL, PORE_BITS_0_63);
+ if (enable) {
+ control |= BE64_BIT(11);
+ } else {
+ control &= ~BE64_BIT(11);
+ }
+ pore_writeReg(p, PORE_R_CONTROL, control, PORE_BITS_0_63);
+ return PORE_SUCCESS;
+}
+
+static int __fake_read(struct pore_bus *b, uint64_t addr,
+ uint8_t *buf, unsigned int len,
+ int *err_code __attribute__((unused)))
+{
+ unsigned int i;
+
+ memset(buf, 0xff, len);
+ dprintf(b->pore, " %-12s: %s(%p, 0x%08llx, ...)\n read: ",
+ b->name, __func__, b, (long long)addr);
+
+ for (i = 0; i < len; i++)
+ dprintf(b->pore, "%02x ", buf[i]);
+ dprintf(b->pore, "\n");
+
+ return len;
+}
+
+static int __fake_write(struct pore_bus *b, uint64_t addr,
+ const uint8_t *buf, unsigned int len,
+ int *err_code __attribute__((unused)))
+{
+ unsigned int i;
+
+ dprintf(b->pore, " %-12s: %s(%p, 0x%08llx, ...)\n write: ",
+ b->name, __func__, b, (long long)addr);
+ for (i = 0; i < len; i++)
+ dprintf(b->pore, "%02x ", buf[i]);
+ dprintf(b->pore, "\n");
+
+ return len;
+}
+
+static int __fake_fetch(struct pore_bus *b, uint64_t pc,
+ uint64_t *ibuf_01 __attribute__((unused)),
+ uint64_t *ibuf_2 __attribute__((unused)),
+ unsigned int *size,
+ int *err_code __attribute__((unused)))
+{
+ dprintf(b->pore, " %-12s: %s(%p, 0x%08llx, ...)\n fetch: ",
+ b->name, __func__, b, (long long)pc);
+
+ *size = 4;
+ return *size;
+}
+
+static int __fake_reset(struct pore_bus *b)
+{
+ dprintf(b->pore, " %s: %s(%p)\n", b->name, __func__, b);
+ return 0;
+}
+
+pore_model_t
+pore_sbe_create(pore_bus_t pib)
+{
+ pore_model_t p;
+ pore_bus_t fi2cm[3], pore2fi2cm;
+
+ p = pore_model_create("SBE");
+ if (!p)
+ return NULL;
+ p->id_flags.ibuf_id = PORE_IBUF_ID_SBE;
+ p->error_mask.val = 0x00BFF00000000000ull; /* FIXME spec undefined */
+
+ /* SEEPROM */
+ p->i2c_e_param[0].i2c_engine_identifier = 0xc;
+ p->i2c_e_param[0].i2c_engine_address_range = 0x2;
+ p->i2c_e_param[0].i2c_engine_port = 0x0;
+ p->i2c_e_param[0].i2c_engine_device_id = 0x0;
+
+ /* OTPROM */
+ p->i2c_e_param[1].i2c_engine_identifier = 0x1;
+ p->i2c_e_param[1].i2c_engine_address_range = 0x2;
+ p->i2c_e_param[1].i2c_engine_port = 0x0;
+ p->i2c_e_param[1].i2c_engine_device_id = 0x0;
+
+ /* PNOR */
+ p->i2c_e_param[2].i2c_engine_identifier = 0xb;
+ p->i2c_e_param[2].i2c_engine_address_range = 0x4;
+ p->i2c_e_param[2].i2c_engine_port = 0x0;
+ p->i2c_e_param[2].i2c_engine_device_id = 0x0;
+
+ /* OCI/MEM Route */
+ p->oci_base[0].val = 0;
+ p->oci_base[0].oci_mem_route = 0xa; /* matches here SEEPROM */
+ p->oci_base[0].oci_base_address = 0x000000000;
+
+ p->oci_base[1].val = 0;
+ p->oci_base[1].oci_mem_route = 0x1; /* matches here OTP */
+ p->oci_base[1].oci_base_address = 0x000000000;
+
+ /* Table base address defines where start and exception vectors are */
+ p->table_base_addr.val = 0;
+ p->table_base_addr.table_base_address = 0x00010008 << 3; /* for SBE */
+
+ /* setup reference for the case it is not yet done. */
+ if (pib)
+ pib->pore = p;
+
+ /* underlying busses which finally implement functionality */
+ if (!pib)
+ pib = poreb_create("PIB", 0, __fake_read, __fake_write,
+ __fake_fetch, __fake_reset);
+
+ fi2cm[0] = poreb_create_fi2cm(p, "FI2CM0", pib, &p->i2c_e_param[0]);
+ fi2cm[1] = poreb_create_fi2cm(p, "FI2CM1", pib, &p->i2c_e_param[1]);
+ fi2cm[2] = poreb_create_fi2cm(p, "FI2CM2", pib, &p->i2c_e_param[2]);
+
+ /* view of PORe engine which goes through remappings
+ before the underlying busses are accessed */
+
+ /* SBE: 3 FI2C masters are servicing this memory range */
+ pore2fi2cm = poreb_create_pore2fi2c(p, "PORE2FI2C",
+ fi2cm[0], fi2cm[1], fi2cm[2]);
+ if (!pore2fi2cm)
+ return NULL;
+
+ pore_attach_mem(p, pore2fi2cm);
+ pore_attach_pib(p, pib);
+
+ return p;
+}
+
+static pore_model_t
+__slw_create(const char *name, pore_bus_t pib, pore_bus_t oci,
+ uint32_t ibuf_id)
+{
+ pore_model_t p;
+ struct pore_bus *pore2oci_b;
+
+ p = pore_model_create(name);
+ if (!p)
+ return NULL;
+ p->id_flags.ibuf_id = ibuf_id;
+ p->error_mask.val = 0x00BFF00000000000ull;
+
+ /* setup reference for the case it is not yet done. */
+ if (pib)
+ pib->pore = p;
+ if (oci)
+ oci->pore = p;
+
+ /* underlying busses which finally implement functionality */
+ if (!pib)
+ pib = poreb_create("PIB", 0, __fake_read, __fake_write,
+ __fake_fetch, __fake_reset);
+
+ if (!oci)
+ oci = poreb_create("OCI", 0, __fake_read, __fake_write,
+ __fake_fetch, __fake_reset);
+
+ /* view of PORe engine which goes through remappings
+ before the underlying busses are accessed */
+
+ /* SLW/GPE0/GPE1: OCI is servicing this memory range */
+ pore2oci_b = poreb_create_pore2oci(p, "PORE2OCI", oci);
+ if (!pore2oci_b)
+ return NULL;
+
+ pore_attach_mem(p, pore2oci_b);
+ pore_attach_pib(p, pib);
+ return p;
+}
+
+pore_model_t
+pore_slw_create(pore_bus_t pib, pore_bus_t oci)
+{
+ return __slw_create("SLW", pib, oci, PORE_IBUF_ID_SLW);
+}
+
+pore_model_t
+pore_gpe0_create(pore_bus_t pib, pore_bus_t oci)
+{
+ return __slw_create("GPE0", pib, oci, PORE_IBUF_ID_GPE0);
+}
+
+pore_model_t
+pore_gpe1_create(pore_bus_t pib, pore_bus_t oci)
+{
+ return __slw_create("GPE1", pib, oci, PORE_IBUF_ID_GPE1);
+}
diff --git a/src/usr/pore/poreve/pore_model/ibuf/pore_regs.h b/src/usr/pore/poreve/pore_model/ibuf/pore_regs.h
new file mode 100644
index 000000000..0376deeff
--- /dev/null
+++ b/src/usr/pore/poreve/pore_model/ibuf/pore_regs.h
@@ -0,0 +1,671 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/pore_model/ibuf/pore_regs.h $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __PORE_REGS__
+#define __PORE_REGS__
+
+/******************************************************************************
+ *
+ * Virtual PORe Engine
+ *
+ *****************************************************************************/
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* 64-bit in IBM notation:
+ 11.1111.1111.2222.2222.2233|3333.3333.4444.4444.4455.5555.5555.6666
+0123.4567.8901.2345.6789.0123.4567.8901|2345.6789.0123.4567.8901.2345.6789.0123
+*/
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t cur_state: 8;
+ uint64_t freeze_action: 1;
+ uint64_t spare : 3;
+ uint64_t stack_pointer : 4;
+ uint64_t pc : 48;
+#else
+ uint64_t pc : 48;
+ uint64_t stack_pointer : 4;
+ uint64_t spare : 3;
+ uint64_t freeze_action: 1;
+ uint64_t cur_state: 8;
+#endif
+ };
+ uint64_t val;
+} pore_status_reg;
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ /* bits 0:3 */
+ uint64_t start_stop : 1;
+ uint64_t continue_step : 1;
+ uint64_t skip : 1;
+ uint64_t set_pc : 1;
+ /* bits 4:7 */
+ uint64_t set_tp_scan_clk : 3;
+ uint64_t lock_exe_trig : 1;
+ /* bits 8:11 */
+ uint64_t freeze_mask : 1;
+ uint64_t check_parity : 1;
+ uint64_t prv_parity : 1;
+ uint64_t trap_enable : 1;
+ /* bits 12:15 */
+ uint64_t tbd : 4;
+ uint64_t pc_brk_pt : 48;
+#else
+ uint64_t pc_brk_pt : 48;
+ uint64_t tbd : 4;
+ uint64_t trap_enable : 1;
+ uint64_t prv_parity : 1;
+ uint64_t check_parity : 1;
+ uint64_t freeze_mask : 1;
+ uint64_t lock_exe_trig : 1;
+ uint64_t set_tp_scan_clk : 3;
+ uint64_t set_pc : 1;
+ uint64_t skip : 1;
+ uint64_t continue_step : 1;
+ uint64_t start_stop : 1;
+
+#endif
+ };
+ uint64_t val;
+} pore_control_reg;
+
+#define PORE_RESET_VALID_BITS 0xe000000000000000ull
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t fn_reset : 1;
+ uint64_t oci_reset : 1;
+ uint64_t restart_sbe_trigger : 1;
+ uint64_t reserved0 : 61;
+#else
+ uint64_t reserved0 : 61;
+ uint64_t restart_sbe_trigger : 1;
+ uint64_t oci_reset : 1;
+ uint64_t fn_reset : 1;
+#endif
+ };
+ uint64_t val;
+} pore_reset_reg;
+
+#define PORE_ERROR_MASK_VALID_BITS 0xfffff80000000000ull
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t enable_err_handler0 : 1;
+ uint64_t enable_err_handler1 : 1;
+ uint64_t enable_err_handler2 : 1;
+ uint64_t enable_err_handler3 : 1;
+
+ uint64_t enable_err_handler4 : 1;
+ uint64_t enable_err_output0 : 1;
+ uint64_t enable_err_output1 : 1;
+ uint64_t enable_err_output2 : 1;
+
+ uint64_t enable_err_output3 : 1;
+ uint64_t enable_err_output4 : 1;
+ uint64_t enable_fatal_error0 : 1;
+ uint64_t enable_fatal_error1 : 1;
+
+ uint64_t enable_fatal_error2 : 1;
+ uint64_t enable_fatal_error3 : 1;
+ uint64_t enable_fatal_error4 : 1;
+ uint64_t stop_exe_on_error0 : 1;
+
+ uint64_t stop_exe_on_error1 : 1;
+ uint64_t stop_exe_on_error2 : 1;
+ uint64_t stop_exe_on_error3 : 1;
+ uint64_t stop_exe_on_error4 : 1;
+
+ uint64_t gate_chiplet_offline_err : 1;
+ uint64_t _reserved0 : 43;
+#else
+ uint64_t _reserved0 : 43;
+ uint64_t gate_chiplet_offline_err : 1;
+
+ uint64_t stop_exe_on_error4 : 1;
+ uint64_t stop_exe_on_error3 : 1;
+ uint64_t stop_exe_on_error2 : 1;
+ uint64_t stop_exe_on_error1 : 1;
+
+ uint64_t stop_exe_on_error0 : 1;
+ uint64_t enable_fatal_error4 : 1;
+ uint64_t enable_fatal_error3 : 1;
+ uint64_t enable_fatal_error2 : 1;
+
+ uint64_t enable_fatal_error1 : 1;
+ uint64_t enable_fatal_error0 : 1;
+ uint64_t enable_err_output4 : 1;
+ uint64_t enable_err_output3 : 1;
+
+ uint64_t enable_err_output2 : 1;
+ uint64_t enable_err_output1 : 1;
+ uint64_t enable_err_output0 : 1;
+ uint64_t enable_err_handler4 : 1;
+
+ uint64_t enable_err_handler3 : 1;
+ uint64_t enable_err_handler2 : 1;
+ uint64_t enable_err_handler1 : 1;
+ uint64_t enable_err_handler0 : 1;
+#endif
+ };
+ uint64_t val;
+} pore_error_mask_reg;
+
+#define PORE_PRV_BASE_ADDRESS_VALID_BITS 0x0000007fffffffffull
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t spare : 25;
+ uint64_t mc : 1;
+ uint64_t chiplet_id : 6;
+ uint64_t reserved0 : 32;
+#else
+ uint64_t reserved0 : 32;
+ uint64_t chiplet_id : 6;
+ uint64_t mc : 1;
+ uint64_t spare : 25;
+#endif
+ };
+ uint64_t val;
+} pore_prv_base_address_reg;
+
+#define PORE_OCI_BASE_ADDRESS_VALID_BITS 0x00003fffffffffffull
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t spare : 18;
+ uint64_t oci_mem_route : 14;
+ /**
+ * oci_mem_route : 14 results in:
+ * 18:32 chiplet_id : 6
+ * 24:27 pib_master : 4;
+ * 28:31 prv_port_no : 4;
+ */
+ uint64_t oci_base_address : 32;
+#else
+ uint64_t oci_base_address : 32;
+ uint64_t oci_mem_route : 14;
+ uint64_t spare : 18;
+#endif
+ };
+ uint64_t val;
+} pore_oci_base_address_reg;
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t reserved : 16;
+ uint64_t memory_space : 16;
+ uint64_t table_base_address : 32;
+#else
+ uint64_t table_base_address : 32;
+ uint64_t memory_space : 16;
+ uint64_t reserved : 16;
+#endif
+ };
+ uint64_t val;
+} pore_table_base_addr_reg;
+
+#define PORE_EXE_TRIGGER_VALID_BITS 0x00fff000ffffffffull
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t reserved : 8;
+ uint64_t start_vector : 4;
+ uint64_t zeroes : 8;
+ uint64_t unused : 12;
+ uint64_t mc_chiplet_select_mask : 32;
+#else
+ uint64_t mc_chiplet_select_mask : 32;
+ uint64_t unused : 12;
+ uint64_t zeroes : 8;
+ uint64_t start_vector : 4;
+ uint64_t reserved : 8;
+#endif
+ };
+ uint64_t val;
+} pore_exe_trigger_reg;
+
+#define PORE_SCRATCH0_VALID_BITS 0x0fffffff00000000ull
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t zeroes : 8;
+ uint64_t scratch0 : 24;
+ uint64_t reserved : 32;
+#else
+ uint64_t reserved : 32;
+ uint64_t scratch0 : 24;
+ uint64_t zeroes : 8;
+#endif
+ };
+ uint64_t val;
+} pore_scratch0_reg;
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t ibuf0 : 32;
+ uint64_t ibuf1 : 32;
+#else
+ uint64_t ibuf1 : 32;
+ uint64_t ibuf0 : 32;
+#endif
+ };
+ uint64_t val;
+} pore_ibuf_01_reg;
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t ibuf2 : 32;
+ uint64_t reserved0 : 32;
+#else
+ uint64_t reserved0 : 32;
+ uint64_t ibuf2 : 32;
+#endif
+ };
+ uint64_t val;
+} pore_ibuf_2_reg;
+
+#define PORE_DBG0_VALID_BITS 0xfffffffff0000000ull
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t last_completed_address : 32;
+ uint64_t filler_bit : 1; /* clearOnAnyWrite */
+ uint64_t last_ret_code_prv : 3; /* clearOnAnyWrite */
+ uint64_t spare : 28; /* clearOnAnyWrite */
+#else
+ uint64_t spare : 28; /* clearOnAnyWrite */
+ uint64_t last_ret_code_prv : 3; /* clearOnAnyWrite */
+ uint64_t filler_bit : 1; /* clearOnAnyWrite */
+ uint64_t last_completed_address : 32;
+#endif
+ };
+ uint64_t val;
+} pore_dbg0_reg;
+
+#define PORE_DBG1_VALID_BITS 0xfffffffffffffffdull
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t pc_last_access : 48;
+ uint64_t oci_master_rd_parity_err : 1;
+ uint64_t last_ret_code_oci : 3;
+ uint64_t bad_instr_parity : 1;
+ uint64_t invalid_instr_code : 1;
+ uint64_t pc_overflow_underrun : 1;
+ uint64_t bad_scan_crc : 1;
+ uint64_t pc_stack_ovflw_undrn_err : 1;
+ uint64_t instruction_fetch_error : 1;
+ uint64_t invalid_instruction_operand : 1;
+ uint64_t invalid_instruction_path : 1;
+ uint64_t invalid_start_vector : 1;
+ uint64_t fi2c_protocol_hang : 1;
+ uint64_t spare : 1;
+ uint64_t debug_regs_locked : 1;
+#else
+ uint64_t debug_regs_locked : 1;
+ uint64_t spare : 1;
+ uint64_t fi2c_protocol_hang : 1;
+ uint64_t invalid_start_vector : 1;
+ uint64_t invalid_instruction_path : 1;
+ uint64_t invalid_instruction_operand : 1;
+ uint64_t instruction_fetch_error : 1;
+ uint64_t pc_stack_ovflw_undrn_err : 1;
+ uint64_t bad_scan_crc : 1;
+ uint64_t pc_overflow_underrun : 1;
+ uint64_t invalid_instr_code : 1;
+ uint64_t bad_instr_parity : 1;
+ uint64_t last_ret_code_oci : 3;
+ uint64_t oci_master_rd_parity_err : 1;
+ uint64_t pc_last_access : 48;
+#endif
+ };
+ uint64_t val;
+} pore_dbg1_reg;
+
+#define PORE_PC_STACK0_VALID_BITS 0xffffffffffff001full
+#define PORE_PC_STACK1_VALID_BITS 0xffffffffffff0000ull
+#define PORE_PC_STACK2_VALID_BITS 0xffffffffffff0000ull
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t pc_stack : 48;
+ uint64_t reserved0 : 11;
+ uint64_t set_stack_pointer : 1; /* clearOnAnyWrite */
+ uint64_t new_stack_pointer : 4; /* clearOnAnyWrite */
+#else
+ uint64_t new_stack_pointer : 4; /* clearOnAnyWrite */
+ uint64_t set_stack_pointer : 1; /* clearOnAnyWrite */
+ uint64_t reserved0 : 11;
+ uint64_t pc_stack : 48;
+#endif
+ };
+ uint64_t val;
+} pore_pc_stack0_reg;
+
+#define PORE_ID_FLAGS_VALID_BITS 0xffffffffffffff0full
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t reserved0 : 32; /* 0..31 */
+ uint64_t pib_parity_fail : 1; /* 32 */
+ uint64_t pib_status : 3; /* 33..35 */
+ uint64_t oci_parity_fail : 1; /* 36 */
+ uint64_t oci_status : 3; /* 37..39 */
+ uint64_t reserved1 : 8; /* 40..47 */
+ uint64_t ugt : 1; /* 48 unsigned greater than */
+ uint64_t ult : 1; /* 49 unsigned less than */
+ uint64_t sgt : 1; /* 50 signed greater than */
+ uint64_t slt : 1; /* 51 signed smaller than */
+ uint64_t c : 1; /* 52 carry */
+ uint64_t o : 1; /* 53 overflow */
+ uint64_t n : 1; /* 54 negative */
+ uint64_t z : 1; /* 55 zero flag */
+ uint64_t reserved2 : 4; /* 56..59 */
+ uint64_t ibuf_id : 4; /* 60..63 */
+#else
+ uint64_t ibuf_id : 4;
+ uint64_t reserved2 : 4;
+ uint64_t z : 1;
+ uint64_t n : 1;
+ uint64_t o : 1;
+ uint64_t c : 1;
+ uint64_t slt : 1;
+ uint64_t sgt : 1;
+ uint64_t ult : 1;
+ uint64_t ugt : 1;
+ uint64_t reserved1 : 8;
+ uint64_t oci_status : 3;
+ uint64_t oci_parity_fail : 1;
+ uint64_t pib_status : 3;
+ uint64_t pib_parity_fail : 1;
+ uint64_t reserved0 : 32;
+#endif
+ };
+ uint64_t val;
+} pore_id_flags_reg;
+
+#define PORE_MEMORY_RELOC_VALID_BITS 0x00000003fffff000ull
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t reserved0 : 30;
+ uint64_t memory_reloc_region : 2;
+ uint64_t memory_reloc_base : 20;
+ uint64_t reserved1 : 12;
+#else
+ uint64_t reserved1 : 12;
+ uint64_t memory_reloc_base : 20;
+ uint64_t memory_reloc_region : 2;
+ uint64_t reserved0 : 30;
+#endif
+ };
+ uint64_t val;
+} pore_memory_reloc_reg;
+
+#define PORE_DATA0_VALID_BITS 0xffffffff00000000ull
+
+#define PORE_I2C_E0_PARAM_VALID_BITS 0xff3f7fff00000000ull
+#define PORE_I2C_E1_PARAM_VALID_BITS 0xff3f7ff000000000ull
+#define PORE_I2C_E2_PARAM_VALID_BITS 0xff3f7ff000000000ull
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t i2c_engine_identifier : 4;
+ uint64_t i2c_engine_address_range : 4;
+ uint64_t reserved1 : 2;
+ uint64_t i2c_engine_port : 6;
+ uint64_t reserved2 : 1;
+ uint64_t i2c_engine_device_id : 7;
+ uint64_t i2c_engine_speed : 8;
+ uint64_t reserved0 : 32;
+#else
+ uint64_t reserved0 : 32;
+ uint64_t i2c_engine_speed : 8;
+ uint64_t i2c_engine_device_id : 7;
+ uint64_t reserved2 : 1;
+ uint64_t i2c_engine_port : 6;
+ uint64_t reserved1 : 2;
+ uint64_t i2c_engine_address_range : 4;
+ uint64_t i2c_engine_identifier : 4;
+
+#endif
+ };
+ uint64_t val;
+} pore_i2c_en_param_reg;
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint32_t r_n_w : 1;
+ uint32_t bc : 1;
+ uint32_t chiplet_select : 6;
+ uint32_t res0 : 4;
+ uint32_t port : 4;
+ uint32_t region_select : 8;
+ uint32_t res1 : 4;
+ uint32_t type_sel_bin : 4;
+#else
+ uint32_t type_sel_bin : 4;
+ uint32_t res1 : 4;
+ uint32_t region_select : 8;
+ uint32_t port : 4;
+ uint32_t res0 : 4;
+ uint32_t chiplet_select : 6;
+ uint32_t bc : 1;
+ uint32_t r_w : 1;
+#endif
+ };
+ uint32_t val;
+} shift_eng_cmd_reg;
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t region_select : 8;
+ uint64_t res0 : 8;
+ uint64_t type_sel_unary : 16;
+ uint64_t res1 : 32;
+#else
+ uint64_t res1 : 32;
+ uint64_t type_sel_unary : 16;
+ uint64_t res0 : 8;
+ uint64_t region_select : 8;
+#endif
+ };
+ uint64_t val;
+} scan_type_select_reg;
+
+/* Scan controller register */
+#define SCAN_REGION_OFFSET 0x0007
+#define SCAN_DATA_OFFSET(cDR, uDR, bits) (0x8000 | \
+ ((cDR) & 0x1) << 14 | \
+ ((uDR) & 0x1) << 13 | \
+ ((bits) & 0x3f))
+
+#ifndef FASTI2C_BASE_OFFSET
+# define FASTI2C_BASE_OFFSET 0x00008000
+#endif
+#define FASTI2C_CONTROL_OFFSET (FASTI2C_BASE_OFFSET + 0x00000000)
+#define FASTI2C_RESET_OFFSET (FASTI2C_BASE_OFFSET + 0x00000001)
+#define FASTI2C_STATUS_OFFSET (FASTI2C_BASE_OFFSET + 0x00000002)
+#define FASTI2C_DATA_OFFSET (FASTI2C_BASE_OFFSET + 0x00000003)
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t with_start : 1;
+ uint64_t with_address : 1;
+ uint64_t read_continue : 1;
+ uint64_t with_stop : 1;
+ uint64_t data_length : 4;
+ uint64_t device_address : 7;
+ uint64_t read_not_write : 1;
+
+ uint64_t speed : 2;
+ uint64_t port_number : 5;
+ uint64_t address_range : 3;
+ uint64_t _reserved0 : 6;
+
+ uint64_t data0 : 8;
+ uint64_t data1 : 8;
+ uint64_t data2 : 8;
+ uint64_t data3 : 8;
+#else
+ uint64_t data3 : 8;
+ uint64_t data2 : 8;
+ uint64_t data1 : 8;
+ uint64_t data0 : 8;
+ uint64_t _reserved0 : 6;
+ uint64_t address_range : 3;
+ uint64_t port_number : 5;
+ uint64_t speed : 2;
+ uint64_t read_not_write : 1;
+ uint64_t device_address : 7;
+ uint64_t data_length : 4;
+ uint64_t with_stop : 1;
+ uint64_t read_continue : 1;
+ uint64_t with_address : 1;
+ uint64_t with_start : 1;
+#endif
+ };
+ uint64_t val;
+} fasti2c_control_reg;
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t pib_address_invalid : 1; /* 0 */
+ uint64_t pib_write_invalid : 1; /* 1 */
+ uint64_t pib_read_invalid : 1; /* 2 */
+ uint64_t pib_address_parity_error : 1; /* 3 */
+ uint64_t pib_parity_error : 1; /* 4 */
+ uint64_t lb_parity_error : 1; /* 5 */
+ uint64_t read_data : 32; /* 6..38 */
+ uint64_t _reserved0 : 6; /* 39..45 */
+ uint64_t i2c_macro_busy : 1; /* 46 */
+ uint64_t i2c_invalid_command : 1;
+ uint64_t i2c_parity_error : 1;
+ uint64_t i2c_back_end_overrun_error : 1;
+ uint64_t i2c_back_end_access_error : 1;
+ uint64_t i2c_arbitration_lost : 1;
+ uint64_t i2c_nack_received : 1;
+ uint64_t i2c_data_request : 1;
+ uint64_t i2c_command_complete : 1;
+ uint64_t i2c_stop_error : 1;
+ uint64_t i2c_port_busy : 1;
+ uint64_t i2c_interface_busy : 1;
+ uint64_t i2c_fifo_entry_count : 8;
+#else
+ uint64_t i2c_fifo_entry_count : 8;
+ uint64_t i2c_interface_busy : 1;
+ uint64_t i2c_port_busy : 1;
+ uint64_t i2c_stop_error : 1;
+ uint64_t i2c_command_complete : 1;
+ uint64_t i2c_data_request : 1;
+ uint64_t i2c_nack_received : 1;
+ uint64_t i2c_arbitration_lost : 1;
+ uint64_t i2c_back_end_access_error : 1;
+ uint64_t i2c_back_end_overrun_error : 1;
+ uint64_t i2c_parity_error : 1;
+ uint64_t i2c_invalid_command : 1;
+ uint64_t i2c_macro_busy : 1;
+ uint64_t _reserved0 : 6;
+ uint64_t read_data : 32;
+ uint64_t lb_parity_error : 1;
+ uint64_t pib_parity_error : 1;
+ uint64_t pib_address_parity_error : 1;
+ uint64_t pib_read_invalid : 1;
+ uint64_t pib_write_invalid : 1;
+ uint64_t pib_address_invalid : 1;
+#endif
+ };
+ uint64_t val;
+} fasti2c_status_reg;
+
+/* Different address definitions */
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t reserved : 16;
+ uint64_t memorySpace : 16;
+ uint64_t offset : 32;
+#else
+ uint64_t offset : 32;
+ uint64_t memorySpace : 16;
+ uint64_t reserved : 16;
+#endif
+ };
+ uint64_t val;
+} PoreAddress;
+
+typedef union {
+ struct {
+#if (__BYTE_ORDER == __BIG_ENDIAN)
+ uint64_t reserved : 33;
+ uint64_t mc : 1;
+ uint64_t chiplet_id : 6;
+ uint64_t pibms_id : 4;
+ uint64_t prv_port : 4;
+ uint64_t local_addr : 16;
+#else
+ uint64_t local_addr : 16;
+ uint64_t prv_port : 4;
+ uint64_t pibms_id : 4;
+ uint64_t chiplet_id : 6;
+ uint64_t mc : 1;
+ uint64_t reserved : 33;
+#endif
+ };
+ uint64_t val;
+} PibAddress;
+
+#ifdef __cplusplus
+} /* closing brace for extern "C" */
+#endif
+
+#endif /* __PORE_REGS__ */
diff --git a/src/usr/pore/poreve/pore_model/include/pore_model.h b/src/usr/pore/poreve/pore_model/include/pore_model.h
new file mode 100644
index 000000000..b7f3bb5a4
--- /dev/null
+++ b/src/usr/pore/poreve/pore_model/include/pore_model.h
@@ -0,0 +1,741 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/pore_model/include/pore_model.h $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __PORE_MODEL__
+#define __PORE_MODEL__
+
+/**
+ * @file pore_model.h
+ * @Author Frank Haverkamp
+ * @date October, 2011
+ *
+ * @brief C interface for the Virtual Power-On-Reset Engine
+ * vPORe. This code should be as portable as possible and have just a
+ * few references to the outside envirnonment. To use this code in the
+ * existing C++ environment one needs to use it together with the vsbe
+ * C++ wrapper.
+ *
+ * The model assumes 4 or 8 byte data in host-byte order. That makes
+ * it necessarry for the outside code to do the endian swapping before
+ * the data is hand over to the model. Same is true for write requests
+ * by the model. Here the data is passed in host-endian order to the
+ * outside of the model.
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Version of the vPORe model */
+#define PORE_MODEL_VERSION 0x0001000C
+
+/**
+ * Different PORe incarations
+ * PORE_GPE has two IBUF instances: IBUF0_ID = 0b0000, IBUF1_ID = 0b0001
+ * PORE_SLW has one IBUF instance: IBUF0_ID = 0b1000
+ * PORE_SBE has one IBUF instance: IBUF0_ID = 0b0100
+ */
+#define PORE_IBUF_ID_GPE0 0x00
+#define PORE_IBUF_ID_GPE1 0x01
+#define PORE_IBUF_ID_SLW 0x08
+#define PORE_IBUF_ID_SBE 0x04
+
+/** Status Codes */
+#define PORE_SUCCESS 0
+#define PORE_IN_RESET 1
+#define PORE_STOPPED 2
+#define PORE_BREAKPOINT_HIT 3
+#define PORE_ERROR_IGNORED 4
+
+/** Error Codes */
+#define PORE_FAILURE -100
+#define PORE_ERR_NOACK -102
+#define PORE_ERR_READ -103
+#define PORE_ERR_WRITE -104
+#define PORE_ERR_FETCH -105
+#define PORE_ERR_DECODE -106
+#define PORE_ERR_EXECUTE -107
+#define PORE_ERR_NOSPACE -108
+#define PORE_ERR_FI2CM -109
+#define PORE_ERR_INVALID_PARAM -110
+#define PORE_ERR_NOT_IMPLEMENTED -111
+#define PORE_ERR_I2C_POLLING -112
+#define PORE_ERR_IN_RESET -113
+#define PORE_ERR_ILLEGAL_FORCED_BRANCH -114
+#define PORE_ERR_NOT_STOPPED -115
+#define PORE_ERR_NOT_STOPPED_WAIT -116
+#define PORE_ERR_BEHAVIOR_NOT_MODELED -117
+#define PORE_ERR_REGISTER_LOCKED -118
+#define PORE_ERR_BUG_INVALID_VECTOR -119
+#define PORE_ERR_INVALID_STACK_POINTER -120
+#define PORE_ERR_STACK_OVERFLOW -121
+#define PORE_ERR_STACK_UNDERFLOW -122
+#define PORE_ERR_INVALID_OPCODE -123
+#define PORE_ERR_UNIMPLEMENTED_INSTR -124
+#define PORE_ERR_INVALID_OPERAND -125
+#define PORE_ERR_HOOK_FAILED -126
+#define PORE_ERR_UNCONNECTED_BUS -127
+#define PORE_ERR_WRITE_ONLY_REGISTER -128
+#define PORE_ERR_READ_ONLY_REGISTER -129
+#define PORE_ERR_FASTI2C_SEQUENCE_ERROR -130
+#define PORE_ERR_FASTI2C_CONTROL_ERROR -131
+#define PORE_ERR_ILLEGAL_REG_OFFSET -132
+#define PORE_ERR_I2CMEMORY_ILLEGAL_ADDR -133
+#define PORE_ERR_NOT_MAPPED_ON_FASTI2C -134
+#define PORE_ERR_BUS_COLLISION -135
+
+/* ... more to come */
+
+/******************************************************************************
+ * PORe Bus: master and slave
+ *****************************************************************************/
+
+/**
+ * @enum pore_PcbReturnCode
+ *
+ * This enumeration follows the 3-bit return code as specified in the
+ * Pervasive Workbook.
+ */
+enum pore_PcbReturnCode {
+ PORE_PCB_SUCCESS = 0,
+ PORE_PCB_RESOURCE_OCCUPIED = 1,
+ PORE_PCB_CHIPLET_OFFLINE = 2,
+ PORE_PCB_PARTIAL_GOOD = 3,
+ PORE_PCB_ADDRESS_ERROR = 4,
+ PORE_PCB_CLOCK_ERROR = 5,
+ PORE_PCB_PACKET_ERROR = 6,
+ PORE_PCB_TIMEOUT = 7
+};
+
+/**
+ * @enum pore_OciReturnCode
+ *
+ * These return codes are abstractions; The OCI_BUS_ERROR is a
+ * catch-all for now.
+ */
+enum pore_OciReturnCode {
+ PORE_OCI_SUCCESS = 0,
+ PORE_OCI_BUS_ERROR = 1
+};
+
+#define PORE_MAX_BUS 64 /** maximum number of possible busses/slaves */
+
+typedef struct pore_bus *pore_bus_t;
+
+typedef int (* poreb_read_f) (pore_bus_t p, uint64_t addr,
+ uint8_t *buf, unsigned int size,
+ int *err_code);
+
+typedef int (* poreb_write_f) (pore_bus_t p, uint64_t addr,
+ const uint8_t *buf, unsigned int size,
+ int *err_code);
+
+typedef int (* poreb_fetch_f) (pore_bus_t p, uint64_t pc,
+ uint64_t *i_buf01, uint64_t *i_buf2,
+ unsigned int *size,
+ int *err_code);
+
+typedef int (* poreb_reset_f) (pore_bus_t p);
+
+
+/**
+ * @brief The pore_bus structure is public because the user should be
+ * able to attach his/her own behavior if needed. The read, write, or
+ * fetch functions are called by the pore-model or by an
+ * address-translation object.
+ */
+struct pore_bus {
+ const char *name; /**< name of the bus, for debug prints */
+ struct pore_model *pore;/**< reference to pore_model */
+
+ poreb_read_f read; /**< read data from bus */
+ poreb_write_f write; /**< write data to bus */
+ poreb_fetch_f fetch; /**< fetch instructions via the bus */
+ poreb_reset_f reset; /**< reset the bus, clear buffers */
+
+ struct pore_bus *slaves[PORE_MAX_BUS]; /** slave devices/busses */
+ uint8_t priv_data[0]; /**< keep internal data here */
+};
+
+static inline void *poreb_get_priv(struct pore_bus *b)
+{
+ return (void *)b->priv_data;
+}
+
+/**
+ * @brief Create PORe bus-object. The user must create own bus-objects
+ * to implement PIB and/or OCI accesses.
+ *
+ * @param [in] pore reference to PORe model
+ * @param [in] name name of this bus-object
+ * @param [in] priv_data_size size of private information
+ * @return NULL on failure, or reference to bus-object
+ */
+struct pore_bus *poreb_create(const char *name,
+ size_t priv_data_size,
+ poreb_read_f r,
+ poreb_write_f w,
+ poreb_fetch_f f,
+ poreb_reset_f R);
+
+/**
+ * @brief Destroy poreb-bus.
+ *
+ * @param [in] b reference to PORe bus
+ */
+void poreb_destroy(pore_bus_t b);
+
+/**
+ * @brief Attach a slave to a bus-object.
+ *
+ * @param [in] b reference to bus-object
+ * @param [in] s reference to bus-object which should be attached to b
+ * @return PORE_SUCCESS, or negative error code
+ */
+int poreb_attach_slave(struct pore_bus *b, struct pore_bus *s);
+
+/**
+ * @brief Read data from bus.
+ *
+ * @param [in] p reference to PORe model
+ * @param [in] addr address for data access
+ * @param [in] buf address where data should be written to
+ * @param [in] size size of buf in bytes
+ * @param [out] err_code Bus error code @see pore_PcbReturnCode,
+ * @see pore_OciReturnCode
+ */
+int poreb_read (pore_bus_t p, uint64_t addr, uint8_t *buf,
+ unsigned int size, int *err_code);
+
+/**
+ * @brief Write data to bus.
+ *
+ * @param [in] p reference to PORe model
+ * @param [in] addr address for data access
+ * @param [in] buf address of the data
+ * @param [in] size size of buf in bytes
+ * @param [out] err_code Bus error code @see pore_PcbReturnCode,
+ * @see pore_OciReturnCode
+ */
+int poreb_write(pore_bus_t p, uint64_t addr, const uint8_t *buf,
+ unsigned int size, int *err_code);
+
+/**
+ * @brief Fetch instruction from bus.
+ *
+ * @param [in] p reference to PORe model
+ * @param [in] pc address for data access
+ * @param [out] i_buf01 1st part of the instruction
+ * @param [out] i_buf2 2nd part of the instruction (only for large instr.)
+ * @param [out] size 4 for normal instr. and 12 for large instr.
+ * @param [out] err_code Bus error code @see pore_PcbReturnCode,
+ * @see pore_OciReturnCode
+ */
+int poreb_fetch(pore_bus_t p, uint64_t pc, uint64_t *i_buf01,
+ uint64_t *i_buf2, unsigned int *size, int *err_code);
+
+/**
+ * @brief Reset the PORe model. Including all busses attached to it.
+ *
+ * @param [in] p reference to PORe model
+ */
+int poreb_reset(pore_bus_t p);
+
+/**
+ * @brief Create fast i2c bus-object.
+ *
+ * @bugs An I2C controller can support more than one ports and it can
+ * also have more than one device listening on one of those. Just like
+ * real world I2C busses connected to an I2C master with an output
+ * multiplexor. For our purpose one i2c_port with one device address
+ * is enough.
+ *
+ * @param [in] name Name of fi2c device
+ * @param [in] mem_buf Memory area used to emulate content
+ * @param [in] mem_size Size of memory area
+ * @param [in] mem_start Start offset of memory area, e.g. LPC bus has
+ * flash at end
+ * @param [in] prv_port Pervasive port number (part of the address)
+ * @param [in] address_bytes Number of required address bytes
+ * @param [in] i2c_port Pervasive I2C masters support muxing multiple
+ * I2C ports
+ * @param [in] deviceAddress Address of the to be accessed I2C chip
+ * @return Pointer to pore_bus object, or NULL in case of
+ * failure
+ */
+struct pore_bus *poreb_create_fi2c(const char *name,
+ uint8_t *mem_buf,
+ unsigned int mem_size,
+ unsigned int mem_start,
+ unsigned int prv_port,
+ unsigned int address_bytes,
+ unsigned int i2c_port,
+ unsigned int deviceAddress);
+
+/******************************************************************************
+ * PORe Model
+ *****************************************************************************/
+
+/**
+ * @brief Reference to PORe model. This reference is used for all functions
+ * dealing with the PORe model.
+ */
+typedef struct pore_model *pore_model_t; /** Representation of the virtual
+ PORE model */
+
+/**
+ * @brief Functions to create different instances of a PORe model.
+ * @see pore_sbe_create, pore_slw_create, pore_gpe0_create, and
+ * pore_gpe1_create.
+ */
+pore_model_t pore_model_create(const char *name);
+
+/**
+ * @brief Destroy poreb-bus.
+ * @param [in] p reference to PORe model
+ */
+void pore_model_destroy(pore_model_t p);
+
+void pore_relocateAddress(pore_model_t p, uint64_t *address);
+
+/**
+ * @brief Create pore-bus object which can be used to implement
+ * selfscomming behavior when attached as slave to the PIB
+ * implementation.
+ *
+ * @param [in] name Name of fi2c device
+ * @param [in] prv_port Pervasive port number (part of the address)
+ * @return Pointer to pore_bus object, or NULL in case of
+ * failure
+ */
+struct pore_bus *poreb_create_selfscom(const char *name,
+ unsigned int chiplet_id,
+ unsigned int prv_port);
+
+/**
+ * @brief Attach MEM/OCI bus to PORe model. This includes setting up
+ * the pore member variable of the pore_bus_t object recursively.
+ *
+ * @param [in] p reference to PORe model
+ * @param [in] b referenct to OCI/MEM bus-object
+ */
+int pore_attach_mem(pore_model_t p, struct pore_bus *b);
+
+/**
+ * @brief Unit2: PORE_SBE (1 thread self-boot engine to support
+ * initial booting)
+ *
+ * @param [in] pib reference to pib bus-object
+ * @return NULL on error, or reference PORe model
+ */
+pore_model_t pore_sbe_create (pore_bus_t pib);
+
+/**
+ * @brief Unit1: PORE_SLW (1 thread engine for waking-up from sleep
+ * and winkle modes)
+ *
+ * @param [in] pib reference to pib bus-object
+ * @param [in] oci reference to oci bus-object
+ * @return NULL on error, or reference PORe model
+ */
+pore_model_t pore_slw_create (pore_bus_t pib, pore_bus_t oci);
+
+/**
+ * @brief Unit0: PORE_GPE (2 thread engine to replace OCA)
+ *
+ * @param [in] pib reference to pib bus-object
+ * @param [in] oci reference to oci bus-object
+ * @return NULL on error, or reference PORe model
+ */
+pore_model_t pore_gpe0_create (pore_bus_t pib, pore_bus_t oci);
+
+/**
+ * @brief Unit0: PORE_GPE (2 thread engine to replace OCA)
+ *
+ * @param [in] pib reference to pib bus-object
+ * @param [in] oci reference to oci bus-object
+ * @return NULL on error, or reference PORe model
+ */
+pore_model_t pore_gpe1_create (pore_bus_t pib, pore_bus_t oci);
+
+void pore_reset(pore_model_t p);
+int pore_step(pore_model_t p);
+int pore_run(pore_model_t p, int steps);
+
+typedef enum {
+ PORE_R_STATUS = 0x00,
+ PORE_R_CONTROL = 0x08,
+ PORE_R_RESET = 0x10,
+ PORE_R_ERROR_MASK = 0x18,
+ PORE_R_PRV_BASE_ADDR0 = 0x20,
+ PORE_R_PRV_BASE_ADDR1 = 0x28,
+ PORE_R_OCI_MEMORY_BASE_ADDR0 = 0x30,
+ PORE_R_OCI_MEMORY_BASE_ADDR1 = 0x38,
+ PORE_R_TABLE_BASE_ADDR = 0x40,
+ PORE_R_EXE_TRIGGER = 0x48,
+ PORE_R_SCRATCH0 = 0x50,
+ PORE_R_SCRATCH1 = 0x58,
+ PORE_R_SCRATCH2 = 0x60,
+ PORE_R_IBUF_01 = 0x68,
+ PORE_R_IBUF_2 = 0x70,
+ PORE_R_DBG0 = 0x78,
+ PORE_R_DBG1 = 0x80,
+ PORE_R_PC_STACK0 = 0x88,
+ PORE_R_PC_STACK1 = 0x90,
+ PORE_R_PC_STACK2 = 0x98,
+ PORE_R_ID_FLAGS = 0xa0,
+ PORE_R_DATA0 = 0xa8,
+ PORE_R_MEM_RELOC = 0xb0,
+ PORE_R_I2C_E0_PARAM = 0xb8,
+ PORE_R_I2C_E1_PARAM = 0xc0,
+ PORE_R_I2C_E2_PARAM = 0xc8,
+ /* ------------------------------ */
+ /* 4 x uint64_t internal state */
+ PORE_R_SIZEOF_PORE_STATE = 0xf0, /**< size of PORe state */
+ PORE_R_ILLEGAL = 0xff, /**< illegal offs, err checking */
+} pore_reg_t; /**< register encodings */
+
+/** Bits 0:31 of a 64-bit register */
+#define PORE_BITS_0_31 0xffffffff00000000ull
+
+/** Bits 32:63 of a 64-bit register */
+#define PORE_BITS_32_63 0x00000000ffffffffull
+
+/** Bits 0:63 of a 64-bit register */
+#define PORE_BITS_0_63 0xffffffffffffffffull
+
+/**
+ * @brief Write to PORe register _with_ side effects.
+ *
+ * @param [in] p reference to pore_model
+ * @param [in] reg register id
+ * @param [in] d data
+ * @param [in] msk mask for write. 4 and 8 bytes are supported
+ * Use PORE_BITS_0_31, PORE_BITS_32_63 PORE_BITS_0_63.
+ * @return 0 on success, else negative error code
+ */
+int pore_writeReg(pore_model_t p, pore_reg_t reg, uint64_t d, uint64_t msk);
+
+/**
+ * @brief Read PORe register _with_ side effects.
+ *
+ * @param [in] p reference to pore_model
+ * @param [in] reg register id
+ * @param [in] msk mask for read. 4 and 8 bytes are supported
+ * Use PORE_BITS_0_31, PORE_BITS_32_63 PORE_BITS_0_63.
+ * @return value of register to read
+ */
+uint64_t pore_readReg(pore_model_t p, pore_reg_t reg, uint64_t msk);
+
+/**
+ * @brief Writes are done _without_ side effects.
+ *
+ * @param [in] p reference to pore_model
+ * @param [in] reg register id
+ * @param [in] d data
+ * @param [in] msk mask for read/write. 4 and 8 bytes are supported
+ * Use PORE_BITS_0_31, PORE_BITS_32_63 PORE_BITS_0_63.
+ * @return 0 on success, else negative error code
+ */
+int pore_writeRegRaw(pore_model_t p, pore_reg_t reg, uint64_t d, uint64_t msk);
+
+/**
+ * @brief Reads are done _without_ side effects.
+ *
+ * @param [in] p reference to pore_model
+ * @param [in] reg register id
+ * @param [in] msk mask for read/write. 4 and 8 bytes are supported
+ * Use PORE_BITS_0_31, PORE_BITS_32_63 PORE_BITS_0_63.
+ * @return value of register to read
+ */
+uint64_t pore_readRegRaw(pore_model_t p, pore_reg_t reg, uint64_t msk);
+
+/**
+ * @brief The pore_state_t structure defines the state of the
+ * model. It is used to backup and restore the model state via
+ * pore_extractState and pore_installState. The structure contains the
+ * architected registers first and the model/implementation specific
+ * data hidden at the end. When installing the state the resources
+ * are restored without any hardware side effects compared to the
+ * regular writeReg, readReg functionality.
+ *
+ * @note The size of the structure must not exceed
+ * PORE_R_SIZEOF_PORE_STATE.
+ */
+typedef struct pore_state {
+ /** start of architected register set */
+ uint64_t status; /* 0x00000000 */
+ uint64_t pore_control; /* 0x00000008 */
+ uint64_t pore_reset; /* 0x00000010 */
+ uint64_t pore_error_mask; /* 0x00000018 */
+ uint64_t prv_base0; /* 0x00000020 */
+ uint64_t prv_base1; /* 0x00000028 */
+ uint64_t oci_base0; /* 0x00000030 */
+ uint64_t oci_base1; /* 0x00000038 */
+ uint64_t pore_table_base_addr; /* 0x00000040 */
+ uint64_t exe_trigger; /* 0x00000048 */
+ uint64_t scratch0; /* 0x00000050 */
+ uint64_t scratch1; /* 0x00000058 */
+ uint64_t scratch2; /* 0x00000060 */
+ uint64_t ibuf_01; /* 0x00000068 */
+ uint64_t ibuf_2; /* 0x00000070 */
+ uint64_t dbg0; /* 0x00000078 */
+ uint64_t dbg1; /* 0x00000080 */
+ uint64_t pc_stack0; /* 0x00000088 */
+ uint64_t pc_stack1; /* 0x00000090 */
+ uint64_t pc_stack2; /* 0x00000098 */
+ uint64_t id_flags; /* 0x000000a0 */
+ uint64_t data0; /* 0x000000a8 */
+ uint64_t memory_reloc; /* 0x000000b0 */
+ uint64_t i2c_e_param[3]; /* 0x000000b8 *
+ * 0x000000c0 *
+ * 0x000000c8 */
+ /** end of architected register set */
+
+ uint64_t priv[4]; /* private data */
+} pore_state_t;
+
+/**
+ * @brief pore_extract is used to extract the current state of the
+ * model. Using those functions will not cause register read/write
+ * side effects.
+ *
+ * @param [in] p reference to pore_model
+ * @param [in] s reference to the pore_state structure which needs to be
+ * provided by the caller.
+ * @return 0 on success, else negative error code
+ */
+int pore_extractState (pore_model_t p, pore_state_t *s);
+
+/**
+ * @brief pore_install is used to isntall the current state of the
+ * model. Using those functions will not cause register read/write
+ * side effects.
+ *
+ * @param [in] p reference to pore_model
+ * @param [in] s reference to the pore_state structure which needs to be
+ * provided by the caller.
+ * @return 0 on success, else negative error code
+ */
+int pore_installState (pore_model_t p, const pore_state_t *s);
+
+/**
+ * @brief Print out model status and registers. This function is
+ * mainly intended for debugging the model.
+ *
+ * @param [in] p reference to pore_model
+ */
+void pore_dump (pore_model_t p);
+
+/**
+ * @brief pore_get|setpriv are used to store private data for
+ * Hook and Callbacks. Use the set function to store and the
+ * get function to retrieve the data.
+ *
+ * @param [in] p reference to pore_model
+ * @param [in] priv private data
+ */
+void pore_setpriv (pore_model_t p, void *priv);
+void *pore_getpriv (pore_model_t p);
+
+/**
+ * @brief The instruction hook call back is called whenever a "hook"
+ * instruction got decoded.
+ */
+typedef int (* instrHook_f) (pore_model_t p, uint64_t addr, uint32_t im24,
+ uint64_t im64);
+/**
+ * @brief The read hook call back is called before a read to the PIB
+ * or OCI bus-object is done.
+ */
+typedef int (* readHook_f) (pore_model_t p, uint64_t addr);
+
+/**
+ * @brief The write hook call back is called before a write to the PIB
+ * or OCI bus-object is done.
+ */
+typedef int (* writeHook_f) (pore_model_t p, uint64_t addr);
+
+/**
+ * @brief The fetch hook call back is called before a fetch from the
+ * PIB or OCI bus-object is done.
+ */
+typedef int (* fetchHook_f) (pore_model_t p, uint64_t addr);
+
+/**
+ * @brief The decode call back is called before a fetched instruction
+ * gets decoded.
+ */
+typedef int (* decodeHook_f) (pore_model_t p, uint8_t *instr,
+ unsigned int size);
+/**
+ * @brief waitCallback_f functions will be called when certain events or
+ * situations occur within the model. E.g. if a delay is required the
+ * outside code has to implement the correct wait time since the model
+ * has no knowledge about the time.
+ */
+typedef void (* waitCallback_f) (pore_model_t p, uint32_t delay);
+
+/**
+ * @brief errorCallback_f is called on an error. There are "normal" as
+ * well as "fatal" errors which can occur.
+ */
+typedef void (* errorCallback_f) (pore_model_t p);
+
+/** pore_bus implementation needs to call some the hook callbacks */
+int pore_instrHook (pore_model_t p, uint64_t addr,
+ uint32_t im24, uint64_t im64);
+int pore_readHook (pore_model_t p, uint64_t addr);
+int pore_writeHook (pore_model_t p, uint64_t addr);
+int pore_fetchHook (pore_model_t p, uint64_t addr);
+
+/**
+ * @brief Hooks will be called with p as parameter. Use
+ * pore_set/getpriv to keep internal data. Hooks are expected to
+ * return 0 on success. If they do not return 0 the model will stop
+ * executing.
+ */
+int pore_registerHooks(pore_model_t p,
+ instrHook_f instrHook,
+ readHook_f readHook,
+ writeHook_f writeHook,
+ fetchHook_f fetchHook,
+ decodeHook_f decodeHook);
+
+void pore_set_enableHookInstr(pore_model_t p, int enabled);
+int pore_get_enableHookInstr(pore_model_t p);
+void pore_set_enableAddressHooks(pore_model_t p, int enabled);
+int pore_get_enableAddressHooks(pore_model_t p);
+
+/**
+ * @brief Register callback functions.
+ *
+ * @param [in] p reference to pore model
+ * @param [in] waitCallback called when a wait instruction is executed.
+ * @param [in] errorCallback called when an error occurs.
+ * @param [in] fatalErrorCallback called when a fatal error occurs.
+ */
+int pore_registerCallbacks(pore_model_t p,
+ waitCallback_f waitCallback,
+ errorCallback_f errorCallback,
+ errorCallback_f fatalErrorCallback);
+
+/**
+ * @brief Perform model reset.
+ * @param [in] p reference to pore model
+ */
+int pore_flush_reset(pore_model_t p);
+
+/**
+ * @brief Changes the internal branch location to something else. This
+ * could be used within hooks if there is need to branch to different
+ * code. FIXME Is this really needed? Is this not dangerous and error
+ * prone?
+ *
+ * @param [in] p reference to pore model
+ * @param [in] addr new program counter
+ */
+int pore_forceBranch(pore_model_t p, uint64_t addr);
+
+#define PORE_TRACE_ERR 0x0001 /**< trace error situations */
+#define PORE_TRACE_IBUF 0x0002 /**< trace fetch/decode/execute */
+#define PORE_TRACE_BUS 0x0004 /**< trace bus events */
+#define PORE_TRACE_I2C 0x0008 /**< trace i2c transactions */
+#define PORE_TRACE_PIB 0x0010 /**< trace PIB traffic */
+#define PORE_TRACE_MEM 0x0020 /**< trace OCI/MEM traffic */
+#define PORE_TRACE_ALL ( PORE_TRACE_ERR | PORE_TRACE_IBUF | \
+ PORE_TRACE_BUS | PORE_TRACE_I2C | \
+ PORE_TRACE_PIB | PORE_TRACE_MEM )
+
+/**
+ * @brief The PORe model supports tracing the execution flow for
+ * debugging. Different code areas have individual trace enable
+ * bits. To print out the trace the instantiator has to provide a
+ * vprintf function which will get called when tracing is enabled.
+ *
+ * @param [in] p reference to pore model
+ * @param [in] trace bitfield identifying the areas which should be trace.
+ */
+void pore_set_trace(pore_model_t p, uint64_t trace);
+uint64_t pore_get_trace(pore_model_t p);
+
+/**
+ * @brief The following function are for easy model operation. They
+ * make use of the side effects when writing to the PORe control
+ * register to start/stop the engine or to set/clear breakpoints of
+ * the program counter PC.
+ */
+
+/**
+ * @brief Stop a potentially running pore-model via write to
+ * PORE_R_CONTROL register.
+ *
+ * @param [in] p reference to pore model
+ */
+int pore_stop(pore_model_t p);
+
+/**
+ * @brief Start pore-model via write to PORE_R_CONTROL register.
+ *
+ * @param [in] p reference to pore model
+ */
+int pore_start(pore_model_t p);
+
+/**
+ * @brief Set program counter to given address. This involves stopping
+ * the engine and setting the program counter via PORE_R_CONTROL
+ * register. After calling this funnction the engine will stay
+ * stopped.
+ *
+ * @param [in] p reference to pore model
+ * @param [in] pc new program counter content
+ */
+int pore_setPc(pore_model_t p, uint64_t pc);
+
+/**
+ * @brief Set a pore-model breakpoint. This is done by using the
+ * PORE_R_CONTROL register. When the pore-model hits the breakpoint
+ * address it will automatically stop.
+ *
+ * @param [in] p reference to pore model
+ * @param [in] bp breakpoint address
+ */
+int pore_setBreakpoint(pore_model_t p, uint64_t bp);
+
+/**
+ * @brief Enable/disable the trap instruction by setting the
+ * appropriate bit in the PORE_R_CONTROL register.
+ *
+ * @param [in] p reference to pore model
+ * @param [in] enable 0: disable, 1: enable
+ */
+int pore_enableTrap(pore_model_t p, int enable);
+
+#ifdef __cplusplus
+} /* closing brace for extern "C" */
+#endif
+
+#endif /* __PORE_MODEL_H__ */
diff --git a/src/usr/pore/poreve/pore_model/include/pore_wrap.h b/src/usr/pore/poreve/pore_model/include/pore_wrap.h
new file mode 100644
index 000000000..370ea378e
--- /dev/null
+++ b/src/usr/pore/poreve/pore_model/include/pore_wrap.h
@@ -0,0 +1,102 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/pore_model/include/pore_wrap.h $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2011
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __PORE_TRACE_H__
+#define __PORE_TRACE_H__
+
+/**
+ * @file pore_interface.h (for HostBoot environment)
+ * @Author Thi Tran
+ * @date October, 2011
+ *
+ * @brief Trace functions for the Virtual Power-On-Reset Engine vPORe.
+ * Since different users of this code use different ways of tracing,
+ * It should be possible to replace the pore_model tracing with a
+ * private version. In this file we use libc printfs to trace the flow
+ * of the code if needed.
+ *
+ */
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <trace/interface.H>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern trace_desc_t* g_poreDbgTd;
+extern trace_desc_t* g_poreErrTd;
+
+#ifndef htobe32
+# if __BYTE_ORDER == __LITTLE_ENDIAN
+# define htobe32(x) __bswap_32 (x)
+# define htole32(x) (x)
+# define be32toh(x) __bswap_32 (x)
+# define le32toh(x) (x)
+
+# define htobe64(x) __bswap_64 (x)
+# define htole64(x) (x)
+# define be64toh(x) __bswap_64 (x)
+# define le64toh(x) (x)
+# else
+# define htobe32(x) (x)
+# define htole32(x) __bswap_32 (x)
+# define be32toh(x) (x)
+# define le32toh(x) __bswap_32 (x)
+
+# define htobe64(x) (x)
+# define htole64(x) __bswap_64 (x)
+# define be64toh(x) (x)
+# define le64toh(x) __bswap_64 (x)
+# endif
+#endif
+
+/** Using the following macros should help to adopt the code to
+ different environments. */
+#define pore_htobe64(x) htobe64(x)
+#define pore_be64toh(x) be64toh(x)
+#define pore_htobe32(x) htobe32(x)
+#define pore_be32toh(x) be32toh(x)
+
+// Debug trace
+// '((void)p);' is to avoid unused variable error when compiling
+#define printf(fmt, args...) TRACFCOMP(g_poreDbgTd, fmt, ##args)
+#define aprintf(fmt, args...) TRACDCOMP(g_poreDbgTd, fmt, ##args)
+#define eprintf(p, fmt, args...) ((void)p); TRACDCOMP(g_poreDbgTd, fmt, ##args)
+#define dprintf(p, fmt, args...) ((void)p); TRACDCOMP(g_poreDbgTd, fmt, ##args)
+#define bprintf(p, fmt, args...) ((void)p); TRACDCOMP(g_poreDbgTd, fmt, ##args)
+#define iprintf(p, fmt, args...) ((void)p); TRACDCOMP(g_poreDbgTd, fmt, ##args)
+#define pib_printf(p, fmt, args...) ((void)p); TRACDCOMP(g_poreDbgTd, fmt, ##args)
+#define mem_printf(p, fmt, args...) ((void)p); TRACDCOMP(g_poreDbgTd, fmt, ##args)
+
+// Diagnostic aid
+#define BUG() \
+ TRACFCOMP(g_poreErrTd, ">>> Bug trapped at %s:%d", \
+ __FILE__, __LINE__ )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PORE_TRACE_H__ */
diff --git a/src/usr/pore/poreve/pore_model/include/vsbe.H b/src/usr/pore/poreve/pore_model/include/vsbe.H
new file mode 100644
index 000000000..393053303
--- /dev/null
+++ b/src/usr/pore/poreve/pore_model/include/vsbe.H
@@ -0,0 +1,193 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/pore_model/include/vsbe.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_H
+#define __VSBE_H
+
+/**
+ * @file vsbe.H
+ * @Author Andre Hertwig with additions by Frank Haverkamp
+ * @date October, 2011
+ *
+ * @brief The interface between the vsbe::PoreModel and the virtual
+ * pore engine model.
+ */
+
+#include "transaction.H"
+#include "modelerror.H"
+#include "poremodel.H"
+#include "poreinterface.H"
+#include "pore_model.h"
+
+#define PORE_UNRUNNABLE "The PORE engine is not runnable without some control action"
+
+namespace vsbe {
+ /** Hooks */
+ int vsbeHookReadCallBack (pore_model_t p, uint64_t i_address);
+ int vsbeHookWriteCallBack (pore_model_t p, uint64_t i_address);
+ int vsbeHookFetchCallBack (pore_model_t p, uint64_t i_address);
+ int vsbeHookDecodeCallBack(pore_model_t p, uint8_t *instr,
+ unsigned int size);
+ int vsbeHookInstructionCallBack(pore_model_t p, uint64_t i_address,
+ uint32_t i_hook, uint64_t i_parameter);
+
+
+ /** Signals */
+ void stoppedIntrCallBack(pore_model_t p);
+ void fatalErrorIntrCallBack(pore_model_t p);
+ void errorIntrCallBack(pore_model_t p);
+ void waitIntrCallBack(pore_model_t p, uint32_t delay);
+
+ /** Data transfer */
+ int vsbePibReadCallBack(pore_bus_t p, uint64_t addr, uint8_t *buf,
+ unsigned int size, int *err_code);
+
+ int vsbePibWriteCallBack(pore_bus_t p, uint64_t addr,
+ const uint8_t *buf, unsigned int size,
+ int *err_code);
+
+ int vsbeOciReadCallBack(pore_bus_t p, uint64_t addr, uint8_t *buf,
+ unsigned int size, int *err_code);
+
+ int vsbeOciWriteCallBack(pore_bus_t p, uint64_t addr,
+ const uint8_t *buf, unsigned int size,
+ int *err_code);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Vsbe
+///////////////////////////////////////////////////////////////////////////////
+
+
+/// Implementation of the vsbe::PoreModel class.
+///
+/// For interface documentation see vsbe::PoreModel.
+
+
+class Vsbe : public vsbe::PoreModel {
+
+public:
+
+ ///////////// vsbe::PoreModel Abstract Interface //////////////////////
+
+ virtual vsbe::ModelError flushReset();
+ virtual vsbe::ModelError step(bool& o_stepped);
+
+ /// @brief Register access with real hardware behavior
+ ///
+ /// Access upper 32-bit:
+ /// registerRead(i_offset, data, 4);
+ /// Access lower 32-bit:
+ /// registerRead(i_offset + 4, data, 4);
+ /// Access 64-bit:
+ /// registerRead(i_offset, data, 8);
+ ///
+ virtual vsbe::ModelError
+ registerRead(const vsbe::PoreRegisterOffset i_offset,
+ uint64_t& o_data, const size_t i_size);
+
+ virtual vsbe::ModelError
+ registerWrite(const vsbe::PoreRegisterOffset i_offset,
+ const uint64_t i_data, const size_t i_size);
+
+ /// @brief Register access without hardware side effects
+ ///
+ /// Access upper 32-bit:
+ /// registerReadRaw(i_offset, data, 4);
+ /// Access lower 32-bit:
+ /// registerReadRaw(i_offset + 4, data, 4);
+ /// Access 64-bit:
+ /// registerReadRaw(i_offset, data, 8);
+ ///
+ virtual vsbe::ModelError
+ registerReadRaw(const vsbe::PoreRegisterOffset i_offset,
+ uint64_t& o_data, const size_t i_size);
+
+ virtual vsbe::ModelError
+ registerWriteRaw(const vsbe::PoreRegisterOffset i_offset,
+ const uint64_t i_data, const size_t i_size);
+
+ virtual vsbe::ModelError enableHookInstruction(bool i_enable);
+ virtual vsbe::ModelError enableAddressHooks(bool i_enable);
+
+ virtual vsbe::ModelError extractState(vsbe::PoreState& o_state);
+ virtual vsbe::ModelError installState(const vsbe::PoreState& i_state);
+ virtual vsbe::ModelError forceBranch(const vsbe::PoreAddress&
+ i_address);
+
+ //////////////// Pmx::Pore Abstract Interface /////////////////////////
+
+ // BB virtual vsbe::ModelError
+ // BB ociTransport(vsbe::OciTransaction *transaction);
+ // BB
+ // BB virtual vsbe::ModelError
+ // BB pibTransport(vsbe::PibTransaction *transaction);
+
+ virtual vsbe::ModelError
+ hookInstruction(const vsbe::PoreAddress& i_address,
+ const uint32_t i_hook,
+ const uint64_t i_parameter);
+
+ virtual vsbe::ModelError hookRead(const vsbe::PoreAddress& i_address);
+ virtual vsbe::ModelError hookWrite(const vsbe::PoreAddress& i_address);
+ virtual vsbe::ModelError hookFetch(const vsbe::PoreAddress& i_address);
+
+ virtual void wait(const uint32_t i_count);
+ virtual void fatalErrorIntr(void);
+ virtual void errorIntr(void);
+
+ ////////////////////////////// Creators ///////////////////////////////
+
+ Vsbe(vsbe::PoreIbufId i_id, vsbe::PoreInterface* i_interface);
+
+ virtual ~Vsbe();
+
+ ////////////////////////////// Manipulators ///////////////////////////
+
+ int pibReadCallBack(pore_bus_t p, uint64_t addr, uint8_t *buf,
+ unsigned int size, int *err_code);
+
+ int pibWriteCallBack(pore_bus_t p, uint64_t addr, const uint8_t *buf,
+ unsigned int size, int *err_code);
+
+ int ociReadCallBack(pore_bus_t p, uint64_t addr, uint8_t *buf,
+ unsigned int size, int *err_code);
+
+ int ociWriteCallBack(pore_bus_t p, uint64_t addr, const uint8_t *buf,
+ unsigned int size, int *err_code);
+
+ ////////////////////////// Implementation /////////////////////////////
+
+
+ /// A vsbe::PibTransaction for PIB mastering
+ vsbe::PibTransaction d_pibTransaction;
+
+ /// A vsbe::OciTransaction for OCI mastering
+ vsbe::OciTransaction d_ociTransaction;
+
+private:
+ struct pore_model *iv_engine;
+ pore_reg_t PoreRegOffs_to_pore(vsbe::PoreRegisterOffset reg);
+ vsbe::PoreRegisterOffset pore_to_PoreRegOffs(pore_reg_t reg);
+};
+
+#endif // __VSBE_H
diff --git a/src/usr/pore/poreve/pore_model/wrapper/vsbe.C b/src/usr/pore/poreve/pore_model/wrapper/vsbe.C
new file mode 100644
index 000000000..ac15807e5
--- /dev/null
+++ b/src/usr/pore/poreve/pore_model/wrapper/vsbe.C
@@ -0,0 +1,692 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/pore_model/wrapper/vsbe.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+/******************************************************************************
+ *
+ * \file vsbe.C
+ * \brief The interface between the vsbe::PoreModel and the Pmx::Pore
+ *
+ *****************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include "vsbe.H"
+#include "pore_model.h"
+#include "pore_wrap.h"
+
+using namespace vsbe;
+
+int vsbe::vsbeHookReadCallBack(pore_model_t p, uint64_t i_address)
+{
+ void *i_vsbe = pore_getpriv(p);
+ return ((Vsbe*)i_vsbe)->hookRead( PoreAddress(i_address) );
+}
+
+int vsbe::vsbeHookWriteCallBack(pore_model_t p, uint64_t i_address)
+{
+ void *i_vsbe = pore_getpriv(p);
+ return ((Vsbe*)i_vsbe)->hookWrite( PoreAddress(i_address) );
+}
+
+int vsbe::vsbeHookFetchCallBack(pore_model_t p, uint64_t i_address)
+{
+ void *i_vsbe = pore_getpriv(p);
+ return ((Vsbe*)i_vsbe)->hookFetch( PoreAddress(i_address) );
+}
+
+void vsbe::fatalErrorIntrCallBack(pore_model_t p)
+{
+ void *i_vsbe = pore_getpriv(p);
+ ((Vsbe*)i_vsbe)->fatalErrorIntr();
+}
+
+void vsbe::errorIntrCallBack(pore_model_t p)
+{
+ void *i_vsbe = pore_getpriv(p);
+ ((Vsbe*)i_vsbe)->errorIntr();
+}
+
+void vsbe::waitIntrCallBack(pore_model_t p, uint32_t delay)
+{
+ void *i_vsbe = pore_getpriv(p);
+ /** delay == 0 means engine is halted on a WAIT instruction */
+ ((Vsbe*)i_vsbe)->wait(delay);
+}
+
+int vsbe::vsbeHookInstructionCallBack(pore_model_t p, uint64_t i_address,
+ uint32_t i_hook, uint64_t i_parameter)
+{
+ void* i_vsbe = pore_getpriv(p);
+ return ((Vsbe*)i_vsbe)->hookInstruction( PoreAddress(i_address),
+ i_hook, i_parameter );
+}
+
+////// OCI and PIB Transactions //////////////////////////////////////////////
+
+int vsbe::vsbePibReadCallBack(pore_bus_t b, uint64_t addr, uint8_t *buf,
+ unsigned int size, int *err_code)
+{
+ Vsbe *vsbe = *(Vsbe **)poreb_get_priv(b);
+ return vsbe->pibReadCallBack(b, addr, buf, size, err_code);
+}
+
+int
+Vsbe::pibReadCallBack(pore_bus_t b, uint64_t addr, uint8_t *buf,
+ unsigned int size, int *err_code)
+{
+ PibTransaction pibTransaction;
+
+ pibTransaction.iv_address = addr;
+ pibTransaction.iv_offset = 0;
+ pibTransaction.iv_data = 0;
+ pibTransaction.iv_mode = vsbe::ACCESS_MODE_READ;
+
+ pibMaster(pibTransaction);
+ *err_code = pibTransaction.iv_pcbReturnCode;
+
+ if (pibTransaction.iv_pcbReturnCode) {
+ size = PORE_ERR_READ;
+ }
+
+ *((uint64_t *)buf) = (*((uint64_t *)(void *)&pibTransaction.iv_data));
+ return size;
+}
+
+
+int vsbe::vsbePibWriteCallBack(pore_bus_t b, uint64_t addr,
+ const uint8_t *buf,
+ unsigned int size,
+ int *err_code)
+{
+ Vsbe *vsbe = *(Vsbe **)poreb_get_priv(b);
+ return vsbe->pibWriteCallBack(b, addr, buf, size, err_code);
+}
+
+
+int
+Vsbe::pibWriteCallBack(pore_bus_t b, uint64_t addr, const uint8_t *buf,
+ unsigned int size, int *err_code)
+{
+ PibTransaction pibTransaction;
+
+ pibTransaction.iv_address = addr;
+ pibTransaction.iv_offset = 0;
+ pibTransaction.iv_mode = vsbe::ACCESS_MODE_WRITE;
+ *(uint64_t *)(void *)&pibTransaction.iv_data = (*((uint64_t *)buf));
+
+ pibMaster(pibTransaction);
+ *err_code = pibTransaction.iv_pcbReturnCode;
+
+ if (pibTransaction.iv_pcbReturnCode) {
+ size = PORE_ERR_WRITE;
+ }
+ return size;
+}
+
+int vsbe::vsbeOciReadCallBack(pore_bus_t b, uint64_t addr, uint8_t *buf,
+ unsigned int size, int *err_code)
+{
+ Vsbe *vsbe = *(Vsbe **)poreb_get_priv(b);
+ return vsbe->ociReadCallBack(b, addr, buf, size, err_code);
+}
+
+int
+Vsbe::ociReadCallBack(pore_bus_t b, uint64_t addr, uint8_t *buf,
+ unsigned int size, int *err_code)
+{
+ OciTransaction ociTransaction;
+
+ ociTransaction.iv_address = addr;
+ ociTransaction.iv_offset = 0;
+ ociTransaction.iv_data = 0;
+ ociTransaction.iv_mode = vsbe::ACCESS_MODE_READ;
+
+ ociMaster(ociTransaction);
+ *err_code = ociTransaction.iv_ociReturnCode;
+
+ if (ociTransaction.iv_ociReturnCode) {
+ size = PORE_ERR_READ;
+ }
+
+ *((uint64_t *)buf) = (*((uint64_t *)(void *)&ociTransaction.iv_data));
+ return size;
+}
+
+int vsbe::vsbeOciWriteCallBack(pore_bus_t b, uint64_t addr,
+ const uint8_t *buf, unsigned int size,
+ int *err_code)
+{
+ Vsbe *vsbe = *(Vsbe **)poreb_get_priv(b);
+ return vsbe->ociWriteCallBack(b, addr, buf, size, err_code);
+}
+
+
+int
+Vsbe::ociWriteCallBack(pore_bus_t b, uint64_t addr, const uint8_t *buf,
+ unsigned int size, int *err_code)
+{
+ OciTransaction ociTransaction;
+
+ ociTransaction.iv_address = addr;
+ ociTransaction.iv_offset = 0;
+ ociTransaction.iv_mode = vsbe::ACCESS_MODE_WRITE;
+ *(uint64_t *)(void *)&ociTransaction.iv_data = (*((uint64_t *)buf));
+
+ ociMaster(ociTransaction);
+ *err_code = ociTransaction.iv_ociReturnCode;
+
+ if (ociTransaction.iv_ociReturnCode) {
+ size = PORE_ERR_WRITE;
+ }
+ return size;
+}
+
+///////////// vsbe::PoreModel Abstract Interface /////////////////////////////
+
+/// Create a PoreModel
+///
+/// This is the static create() method required to create an
+/// implementation-specific instance of a vsbe::PoreModel.
+
+PoreModel* PoreModel::create(PoreIbufId i_id, PoreInterface *i_interface)
+{
+ return new Vsbe(i_id, i_interface);
+}
+
+ModelError Vsbe::flushReset()
+{
+ return ModelError( pore_flush_reset(iv_engine) );
+}
+
+pore_reg_t Vsbe::PoreRegOffs_to_pore(vsbe::PoreRegisterOffset reg)
+{
+ switch (reg) {
+ case PORE_STATUS: return PORE_R_STATUS;
+ case PORE_CONTROL: return PORE_R_CONTROL;
+ case PORE_RESET: return PORE_R_RESET;
+ case PORE_ERROR_MASK: return PORE_R_ERROR_MASK;
+ case PORE_PRV_BASE_ADDR0: return PORE_R_PRV_BASE_ADDR0;
+ case PORE_PRV_BASE_ADDR1: return PORE_R_PRV_BASE_ADDR1;
+ case PORE_OCI_MEMORY_BASE_ADDR0: return PORE_R_OCI_MEMORY_BASE_ADDR0;
+ case PORE_OCI_MEMORY_BASE_ADDR1: return PORE_R_OCI_MEMORY_BASE_ADDR1;
+ case PORE_TABLE_BASE_ADDR: return PORE_R_TABLE_BASE_ADDR;
+ case PORE_EXE_TRIGGER: return PORE_R_EXE_TRIGGER;
+ case PORE_SCRATCH0: return PORE_R_SCRATCH0;
+ case PORE_SCRATCH1: return PORE_R_SCRATCH1;
+ case PORE_SCRATCH2: return PORE_R_SCRATCH2;
+ case PORE_IBUF_01: return PORE_R_IBUF_01;
+ case PORE_IBUF_2: return PORE_R_IBUF_2;
+ case PORE_DBG0: return PORE_R_DBG0;
+ case PORE_DBG1: return PORE_R_DBG1;
+ case PORE_PC_STACK0: return PORE_R_PC_STACK0;
+ case PORE_PC_STACK1: return PORE_R_PC_STACK1;
+ case PORE_PC_STACK2: return PORE_R_PC_STACK2;
+ case PORE_ID_FLAGS: return PORE_R_ID_FLAGS;
+ case PORE_DATA0: return PORE_R_DATA0;
+ case PORE_MEM_RELOC: return PORE_R_MEM_RELOC;
+ case PORE_I2C_E0_PARAM: return PORE_R_I2C_E0_PARAM;
+ case PORE_I2C_E1_PARAM: return PORE_R_I2C_E1_PARAM;
+ case PORE_I2C_E2_PARAM: return PORE_R_I2C_E2_PARAM;
+ default: return PORE_R_ILLEGAL;
+ }
+ return PORE_R_ILLEGAL;
+}
+
+
+vsbe::PoreRegisterOffset Vsbe::pore_to_PoreRegOffs(pore_reg_t reg)
+{
+ switch (reg) {
+ case PORE_R_STATUS: return PORE_STATUS;
+ case PORE_R_CONTROL: return PORE_CONTROL;
+ case PORE_R_RESET: return PORE_RESET;
+ case PORE_R_ERROR_MASK: return PORE_ERROR_MASK;
+ case PORE_R_PRV_BASE_ADDR0: return PORE_PRV_BASE_ADDR0;
+ case PORE_R_PRV_BASE_ADDR1: return PORE_PRV_BASE_ADDR1;
+ case PORE_R_OCI_MEMORY_BASE_ADDR0: return PORE_OCI_MEMORY_BASE_ADDR0;
+ case PORE_R_OCI_MEMORY_BASE_ADDR1: return PORE_OCI_MEMORY_BASE_ADDR1;
+ case PORE_R_TABLE_BASE_ADDR: return PORE_TABLE_BASE_ADDR;
+ case PORE_R_EXE_TRIGGER: return PORE_EXE_TRIGGER;
+ case PORE_R_SCRATCH0: return PORE_SCRATCH0;
+ case PORE_R_SCRATCH1: return PORE_SCRATCH1;
+ case PORE_R_SCRATCH2: return PORE_SCRATCH2;
+ case PORE_R_IBUF_01: return PORE_IBUF_01;
+ case PORE_R_IBUF_2: return PORE_IBUF_2;
+ case PORE_R_DBG0: return PORE_DBG0;
+ case PORE_R_DBG1: return PORE_DBG1;
+ case PORE_R_PC_STACK0: return PORE_PC_STACK0;
+ case PORE_R_PC_STACK1: return PORE_PC_STACK1;
+ case PORE_R_PC_STACK2: return PORE_PC_STACK2;
+ case PORE_R_ID_FLAGS: return PORE_ID_FLAGS;
+ case PORE_R_DATA0: return PORE_DATA0;
+ case PORE_R_MEM_RELOC: return PORE_MEM_RELOC;
+ case PORE_R_I2C_E0_PARAM: return PORE_I2C_E0_PARAM;
+ case PORE_R_I2C_E1_PARAM: return PORE_I2C_E1_PARAM;
+ case PORE_R_I2C_E2_PARAM: return PORE_I2C_E2_PARAM;
+ default: return PORE_ILLEGAL;;
+ }
+ return PORE_ILLEGAL;
+}
+
+
+//TODO Do we really need o_stepped. Ask Bishop if we can change the interface
+ModelError Vsbe::step(bool& o_stepped)
+{
+ int rc, me;
+
+ o_stepped = false;
+ rc = pore_step(iv_engine);
+ if ((rc == PORE_SUCCESS) || // Normal execution
+ (rc == PORE_ERROR_IGNORED)) // An error was ignored!
+ o_stepped = true;
+
+ if (rc < 0) {
+ /* FIXME Translate internal to external error codes nicely */
+ switch (rc) {
+ case PORE_ERR_HOOK_FAILED:
+ me = ME_HOOK_INSTRUCTION_ERROR; break;
+ case PORE_ERR_READ:
+ me = ME_PORE_MODEL_GENERIC_ERROR; break;
+ case PORE_ERR_WRITE:
+ me = ME_PORE_MODEL_GENERIC_ERROR; break;
+
+ case PORE_ERR_INVALID_OPCODE:
+ default:
+ me = ME_FAILURE; break;
+ }
+ return ModelError(me);
+ }
+
+ return ModelError(ME_SUCCESS);
+}
+
+ModelError Vsbe::registerRead(const vsbe::PoreRegisterOffset i_offset,
+ uint64_t& o_data, const size_t i_size)
+{
+ pore_reg_t reg =
+ PoreRegOffs_to_pore(vsbe::PoreRegisterOffset(i_offset & ~0x7));
+
+ if (((i_offset & 0x7) == 0x4) && (i_size == 4)) { // lower 32-bit
+ o_data = pore_readReg(iv_engine, reg, PORE_BITS_32_63);
+ o_data &= 0xffffffffull;
+ return ME_SUCCESS;
+ }
+ if (((i_offset & 0x7) == 0x0) && (i_size == 4)) { // upper 32-bit
+ o_data = pore_readReg(iv_engine, reg, PORE_BITS_0_31);
+ o_data >>= 32;
+ o_data &= 0xffffffffull;
+ return ME_SUCCESS;
+ }
+ o_data = pore_readReg(iv_engine, reg, PORE_BITS_0_63);
+ return ME_SUCCESS;
+}
+
+ModelError Vsbe::registerWrite(const vsbe::PoreRegisterOffset i_offset,
+ const uint64_t i_data, const size_t i_size)
+{
+ pore_reg_t reg =
+ PoreRegOffs_to_pore(vsbe::PoreRegisterOffset(i_offset & ~0x7));
+
+ if (((i_offset & 0x7) == 0x4) && (i_size == 4)) { // lower 32-bit
+ pore_writeReg(iv_engine, reg, i_data, PORE_BITS_32_63);
+ return ME_SUCCESS;
+ }
+ if (((i_offset & 0x7) == 0x0) && (i_size == 4)) { // upper 32-bit
+ pore_writeReg(iv_engine, reg, i_data << 32, PORE_BITS_0_31);
+ return ME_SUCCESS;
+ }
+ pore_writeReg(iv_engine, reg, i_data, PORE_BITS_0_63);
+ return ME_SUCCESS;
+}
+
+ModelError Vsbe::registerReadRaw(const vsbe::PoreRegisterOffset i_offset,
+ uint64_t& o_data, const size_t i_size)
+{
+ pore_reg_t reg =
+ PoreRegOffs_to_pore(vsbe::PoreRegisterOffset(i_offset & ~0x7));
+
+ if (((i_offset & 0x7) == 0x4) && (i_size == 4)) { // lower 32-bit
+ o_data = pore_readRegRaw(iv_engine, reg, PORE_BITS_32_63);
+ o_data &= 0xffffffffull;
+ return ME_SUCCESS;
+ }
+ if (((i_offset & 0x7) == 0x0) && (i_size == 4)) { // upper 32-bit
+ o_data = pore_readRegRaw(iv_engine, reg, PORE_BITS_0_31);
+ o_data >>= 32;
+ o_data &= 0xffffffffull;
+ return ME_SUCCESS;
+ }
+ o_data = pore_readRegRaw(iv_engine, reg, PORE_BITS_0_63);
+ return ME_SUCCESS;
+}
+
+ModelError Vsbe::registerWriteRaw(const vsbe::PoreRegisterOffset i_offset,
+ const uint64_t i_data, const size_t i_size)
+{
+ pore_reg_t reg =
+ PoreRegOffs_to_pore(vsbe::PoreRegisterOffset(i_offset & ~0x7));
+
+ if (((i_offset & 0x7) == 0x4) && (i_size == 4)) { // lower 32-bit
+ pore_writeRegRaw(iv_engine, reg, i_data, PORE_BITS_32_63);
+ return ME_SUCCESS;
+ }
+ if (((i_offset & 0x7) == 0x0) && (i_size == 4)) { // upper 32-bit
+ pore_writeRegRaw(iv_engine, reg, i_data << 32, PORE_BITS_0_31);
+ return ME_SUCCESS;
+ }
+ pore_writeRegRaw(iv_engine, reg, i_data, PORE_BITS_0_63);
+ return ME_SUCCESS;
+}
+
+ModelError Vsbe::enableHookInstruction(bool i_enable)
+{
+ pore_set_enableHookInstr(iv_engine, i_enable);
+ return ME_SUCCESS;
+}
+
+
+ModelError Vsbe::enableAddressHooks(bool i_enable)
+{
+ pore_set_enableAddressHooks(iv_engine, i_enable);
+ return ME_SUCCESS;
+}
+
+
+// To extract the state we simply read out the current register values.
+//TODO Check what to do with some state registers like BRANCH_TAKEN, ...
+ModelError Vsbe::extractState(vsbe::PoreState& o_state)
+{
+ pore_state_t s;
+ unsigned int reg_id;
+ uint64_t *reg;
+
+ if (PORE_R_SIZEOF_PORE_STATE > (pore_reg_t)SIZEOF_PORE_STATE) {
+ BUG();
+ }
+
+ pore_extractState(iv_engine, &s);
+ for (reg_id = PORE_R_STATUS; reg_id < PORE_R_SIZEOF_PORE_STATE;
+ reg_id += 8) {
+ reg = (uint64_t *)((uint8_t *)&s + reg_id);
+ o_state.put((vsbe::PoreRegisterOffset)reg_id, *reg);
+ }
+
+ return ME_SUCCESS;
+}
+
+
+// To install the state we simply restore the saved register values.
+//TODO Check what to do with some state registers like BRANCH_TAKEN, ...
+
+ModelError Vsbe::installState(const vsbe::PoreState& i_state)
+{
+ uint64_t data;
+ pore_state_t s;
+ unsigned int reg_id;
+ uint64_t *reg;
+
+ if (PORE_R_SIZEOF_PORE_STATE > (pore_reg_t)SIZEOF_PORE_STATE) {
+ BUG();
+ }
+
+ for (reg_id = PORE_R_STATUS; reg_id < PORE_R_SIZEOF_PORE_STATE;
+ reg_id += 8) {
+ reg = (uint64_t *)((uint8_t *)&s + reg_id);
+ i_state.get((vsbe::PoreRegisterOffset)reg_id, data);
+ *reg = data;
+ }
+ pore_installState(iv_engine, &s);
+
+ return ME_SUCCESS;
+}
+
+
+ModelError Vsbe::forceBranch(const vsbe::PoreAddress& i_address)
+{
+ return ModelError ( pore_forceBranch(iv_engine,
+ (uint64_t)i_address) );
+}
+
+#if 0
+/// \bug We can't distinguish READ from EXECUTE
+// Convert a PMX transaction to a VSBE transaction and master it
+ModelError Vsbe::ociTransport(OciTransaction *inTransaction)
+{
+ ModelError me;
+ vsbe::ModelError vsbe_me;
+ OciTransaction transaction;
+ do {
+
+ transaction.iv_address = inTransaction->iv_address;
+
+ if (inTransaction->iv_mode == ACCESS_MODE_READ) {
+ transaction.iv_mode = vsbe::ACCESS_MODE_READ;
+ } else {
+ transaction.iv_mode = vsbe::ACCESS_MODE_WRITE;
+ transaction.iv_data = inTransaction->iv_data;
+ }
+
+ vsbe_me = ociMaster(transaction);
+ if (vsbe_me != 0) {
+ break;
+ }
+
+ if (inTransaction->iv_mode == ACCESS_MODE_READ) {
+ inTransaction->iv_data = transaction.iv_data;
+ }
+ } while (0);
+
+ if (vsbe_me != 0) {
+ modelError(vsbe_me);
+ //TODO What is the right return value for me?
+ // me = OCI_TIMEOUT;
+ me = ME_FAILURE;
+
+ //TODO What is this ?
+ // DUAL_ERROR(vsbe_me, me);
+ } else {
+ me = ME_SUCCESS;
+ }
+ return me;
+}
+
+
+/// \bug We can't distinguish READ from EXECUTE
+// Convert a PMX transaction to a VSBE transaction and master it
+ModelError Vsbe::pibTransport(PibTransaction *inPibTransaction)
+{
+ ModelError me;
+ vsbe::ModelError vsbe_me;
+ PibTransaction pibTransaction;
+
+ do {
+ pibTransaction.iv_address = inPibTransaction->iv_address;
+
+ if (inPibTransaction->iv_mode == vsbe::ACCESS_MODE_READ) {
+ pibTransaction.iv_mode = vsbe::ACCESS_MODE_READ;
+ } else {
+ pibTransaction.iv_mode = vsbe::ACCESS_MODE_WRITE;
+ pibTransaction.iv_data = inPibTransaction->iv_data;
+ }
+
+ vsbe_me = pibMaster(pibTransaction);
+ if (vsbe_me != 0) {
+ break;
+ }
+
+ inPibTransaction->iv_pcbReturnCode =
+ pibTransaction.iv_pcbReturnCode;
+ if (inPibTransaction->iv_mode == vsbe::ACCESS_MODE_READ) {
+ inPibTransaction->iv_data = pibTransaction.iv_data;
+ }
+ } while (0);
+
+ if (vsbe_me != 0) {
+ modelError(vsbe_me);
+ me = inPibTransaction->busError(ME_FAILURE);
+ //TODO What is this ?
+ // DUAL_ERROR(vsbe_me, me);
+ } else {
+ me = ME_SUCCESS;
+ }
+ return me;
+ }
+#endif
+
+ModelError Vsbe::hookInstruction(const PoreAddress& i_address,
+ const uint32_t i_hook,
+ const uint64_t i_parameter)
+{
+ PoreAddress vsbe_address;
+
+ vsbe_address.iv_memorySpace = i_address.iv_memorySpace;
+ vsbe_address.iv_offset = i_address.iv_offset;
+
+ vsbe::PoreModel::hookInstruction(vsbe_address,
+ i_hook,
+ i_parameter);
+ return ME_SUCCESS;
+}
+
+
+ModelError Vsbe::hookRead(const PoreAddress& i_address)
+{
+ vsbe::PoreAddress vsbe_address;
+
+ vsbe_address.iv_memorySpace = i_address.iv_memorySpace;
+ vsbe_address.iv_offset = i_address.iv_offset;
+
+ vsbe::PoreModel::hookRead(vsbe_address);
+ return ME_SUCCESS;
+}
+
+
+ModelError Vsbe::hookWrite(const PoreAddress& i_address)
+{
+ vsbe::PoreAddress vsbe_address;
+
+ vsbe_address.iv_memorySpace = i_address.iv_memorySpace;
+ vsbe_address.iv_offset = i_address.iv_offset;
+
+ vsbe::PoreModel::hookWrite(vsbe_address);
+ return ME_SUCCESS;
+}
+
+
+ModelError Vsbe::hookFetch(const PoreAddress& i_address)
+{
+ vsbe::PoreAddress vsbe_address;
+
+ vsbe_address = i_address;
+ // vsbe_address.iv_memorySpace = i_address.iv_memorySpace;
+ // vsbe_address.iv_offset = i_address.iv_offset;
+
+ vsbe::PoreModel::hookFetch(vsbe_address);
+ return ME_SUCCESS;
+}
+
+void Vsbe::fatalErrorIntr(void)
+{
+ /* aprintf("PORe Model has hit fatalError\n"); */
+ vsbe::PoreModel::fatalErrorIntr();
+}
+
+void Vsbe::errorIntr(void)
+{
+ /* aprintf("PORe Model has hit Error\n"); */
+ vsbe::PoreModel::errorIntr();
+}
+
+void Vsbe::wait(const uint32_t i_count)
+{
+ /* aprintf("PORe Model waits for %d ticks\n", i_count); */
+ vsbe::PoreModel::wait(i_count);
+}
+
+////////////////////////////// Creators //////////////////////////////
+
+Vsbe::Vsbe(PoreIbufId i_id, PoreInterface* i_interface) :
+ PoreModel(i_id, i_interface)
+{
+ struct pore_bus *pibBus, *ociBus;
+ Vsbe **vsbe_p;
+
+ pibBus = poreb_create("PIB_Bus",
+ sizeof(Vsbe *),
+ vsbePibReadCallBack,
+ vsbePibWriteCallBack,
+ NULL, // fetch
+ NULL); // reset
+ if (pibBus == NULL) {
+ BUG();
+ return;
+ }
+ vsbe_p = (Vsbe **)poreb_get_priv(pibBus);
+ *vsbe_p = this;
+
+ ociBus = poreb_create("OCI_Bus",
+ sizeof(Vsbe *),
+ vsbeOciReadCallBack,
+ vsbeOciWriteCallBack,
+ NULL, // fetch
+ NULL); // reset
+ if (pibBus == NULL) {
+ BUG();
+ return;
+ }
+ vsbe_p = (Vsbe **)poreb_get_priv(ociBus);
+ *vsbe_p = this;
+
+ switch (i_id) {
+ case PORE_GPE0:
+ iv_engine = pore_gpe0_create(pibBus, ociBus);
+ break;
+ case PORE_GPE1:
+ iv_engine = pore_gpe1_create(pibBus, ociBus);
+ break;
+ case PORE_SLW:
+ iv_engine = pore_slw_create(pibBus, ociBus);
+ break;
+ case PORE_SBE:
+ iv_engine = pore_sbe_create(pibBus); /* pib */
+ break;
+ default:
+ break;
+ }
+
+ pore_setpriv(iv_engine, (void *)this);
+ pore_registerHooks(iv_engine,
+ vsbeHookInstructionCallBack,
+ vsbeHookReadCallBack,
+ vsbeHookWriteCallBack,
+ vsbeHookFetchCallBack,
+ NULL);
+
+ pore_registerCallbacks(iv_engine,
+ waitIntrCallBack,
+ errorIntrCallBack,
+ fatalErrorIntrCallBack);
+}
+
+Vsbe::~Vsbe()
+{
+ pore_model_destroy(iv_engine); /* done */
+}
diff --git a/src/usr/pore/poreve/porevesrc/bus.C b/src/usr/pore/poreve/porevesrc/bus.C
new file mode 100644
index 000000000..fdf3e90a5
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/bus.C
@@ -0,0 +1,900 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/bus.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// $Id: bus.C,v 1.22 2012/01/05 23:15:54 bcbrock Exp $
+
+/// \file bus.C
+/// \brief PoreVe bus and base device models
+
+#include "bus.H"
+#include <fapi.H>
+#include <transaction.H>
+
+
+
+using namespace vsbe;
+
+//-----------------------------------------------------------------------------
+Bus::Bus() :
+ iv_primarySlaves(NULL),
+ iv_secondarySlaves(NULL)
+{
+}
+
+//-----------------------------------------------------------------------------
+Bus::~Bus()
+{
+}
+
+//-----------------------------------------------------------------------------
+void
+Bus::attachPrimarySlave(Slave* i_slave)
+{
+ if( iv_primarySlaves == 0 )
+ {
+ i_slave->iv_next = 0;
+ }else{
+ i_slave->iv_next = iv_primarySlaves;
+ }
+ iv_primarySlaves = i_slave;
+}
+
+//-----------------------------------------------------------------------------
+void
+Bus::attachSecondarySlave(Slave* i_slave)
+{
+ if( iv_secondarySlaves == 0 )
+ {
+ i_slave->iv_next = 0;
+ }else{
+ i_slave->iv_next = iv_secondarySlaves;
+ }
+ iv_secondarySlaves = i_slave;
+}
+
+
+//-----------------------------------------------------------------------------
+fapi::ReturnCode
+Bus::operation(Transaction& trans)
+{
+ fapi::ReturnCode rc;
+ Slave* slave= 0;
+
+ do
+ {
+ for( slave = iv_primarySlaves; slave; slave = slave->iv_next )
+ {
+ if( (trans.iv_address >= slave->iv_base) && (trans.iv_address < (slave->iv_base + slave->iv_size) ) )
+ {
+ break; // found a primary slave
+ }
+ }
+
+ if( slave == 0 )
+ { // primary slaves did not hold the transaction address. Try using the secondary slaves.
+ for( slave = iv_secondarySlaves; slave; slave = slave->iv_next )
+ {
+ if( (trans.iv_address >= slave->iv_base) && (trans.iv_address < (slave->iv_base + slave->iv_size) ) )
+ {
+ break; // found a secondary slave
+ }
+ }
+ }
+
+ break;
+
+ }while(0);
+
+ do
+ {
+ if( slave == 0 ) // neither primary nor secondary slaves held the address
+ {
+ trans.busError(ME_NOT_MAPPED_ON_BUS);
+ rc= 1;
+ break;
+ }
+
+ if( (trans.iv_mode & slave->iv_permissions) == 0 ){
+ trans.busError(ME_BUS_SLAVE_PERMISSION_DENIED);
+ rc= 1;
+ break;
+ }
+
+ trans.iv_offset = trans.iv_address - slave->iv_base;
+ rc = slave->operation( trans );
+ break;
+ }while(1);
+
+ return rc;
+}
+
+//-----------------------------------------------------------------------------
+Slave::Slave()
+:iv_base(0), iv_size(0), iv_permissions(0),
+iv_next(NULL), iv_target(NULL), iv_dataBuffer(NULL)
+{
+
+}
+
+//-----------------------------------------------------------------------------
+Slave::~Slave()
+{
+}
+
+//-----------------------------------------------------------------------------
+PibSlave::PibSlave()
+{
+}
+
+//-----------------------------------------------------------------------------
+PibSlave::~PibSlave()
+{
+}
+
+//-----------------------------------------------------------------------------
+fapi::ReturnCode
+PibSlave::operation(Transaction& io_transaction)
+{
+ fapi::ReturnCode rc;
+ PibTransaction* pt = (PibTransaction*)&io_transaction;
+
+ if( io_transaction.iv_mode & ACCESS_MODE_READ )
+ {
+ rc = getScom( io_transaction.iv_address, io_transaction.iv_data );
+ }
+ else
+ {
+ rc = putScom( io_transaction.iv_address, io_transaction.iv_data );
+ }
+
+ if( rc.ok() )
+ {
+ pt->iv_pcbReturnCode = PCB_SUCCESS;
+ }
+ else
+ {
+ if( rc & fapi_PCB_RESOURCE_BUSY ){
+ pt->iv_pcbReturnCode = PCB_RESOURCE_OCCUPIED;
+ }else if( rc & fapi_PCB_OFFLINE_ERROR ){
+ pt->iv_pcbReturnCode = PCB_CHIPLET_OFFLINE;
+ }else if( rc & fapi_PCB_PARTIAL_ERROR ){
+ pt->iv_pcbReturnCode = PCB_PARTIAL_GOOD;
+ }else if( rc & fapi_PCB_ADDRESS_ERROR ){
+ pt->iv_pcbReturnCode = PCB_ADDRESS_ERROR;
+ }else if( rc & fapi_PCB_CLOCK_ERROR ){
+ pt->iv_pcbReturnCode = PCB_CLOCK_ERROR;
+ }else if( rc & fapi_PCB_PARITY_ERROR ){
+ pt->iv_pcbReturnCode = PCB_PACKET_ERROR;
+ }else if( rc & fapi_PCB_TIMEOUT_ERROR ){
+ pt->iv_pcbReturnCode = PCB_TIMEOUT;
+ }else{
+ pt->iv_pcbReturnCode = PCB_TIMEOUT;
+ }
+ rc = 0;
+ }
+
+ io_transaction.iv_modelError = ME_SUCCESS;
+ return rc;
+}
+
+
+//-----------------------------------------------------------------------------
+void
+Slave::configure(
+ fapi::Target* i_target,
+ ecmdDataBufferBase* i_dataBuffer,
+ uint32_t i_base,
+ uint64_t i_size,
+ int i_permissions
+ )
+{
+ iv_target = i_target;
+ iv_dataBuffer = i_dataBuffer;
+ iv_base = i_base;
+ iv_size = i_size;
+ iv_permissions = i_permissions;
+ iv_next = NULL;
+}
+
+
+
+//-----------------------------------------------------------------------------
+fapi::ReturnCode
+PibSlave::getScom(const uint32_t i_offset, uint64_t& o_data)
+{
+ fapi::ReturnCode rc;
+ rc = fapiGetScom( *iv_target, i_offset, *iv_dataBuffer );
+ o_data = iv_dataBuffer->getDoubleWord( 0 );
+
+ return rc;
+}
+
+//-----------------------------------------------------------------------------
+fapi::ReturnCode
+PibSlave::putScom(const uint32_t i_offset, const uint64_t i_data)
+{
+ fapi::ReturnCode rc;
+ iv_dataBuffer->setDoubleWordLength( 1 );
+ iv_dataBuffer->setDoubleWord( 0, i_data );
+ rc = fapiPutScom( *iv_target, i_offset, *iv_dataBuffer );
+
+ return rc;
+}
+
+
+//-----------------------------------------------------------------------------
+PibMemory::PibMemory() :
+iv_passThrough(false),iv_memory(NULL)
+{
+}
+
+//-----------------------------------------------------------------------------
+PibMemory::~PibMemory()
+{
+}
+
+//-----------------------------------------------------------------------------
+void
+PibMemory::setPassThrough(const bool i_enable)
+{
+ iv_passThrough = i_enable;
+}
+
+//-----------------------------------------------------------------------------
+void
+PibMemory::configure(
+ fapi::Target* i_target,
+ ecmdDataBufferBase* i_dataBuffer,
+ uint32_t i_base,
+ uint64_t i_size,
+ int i_permissions,
+ Memory* i_memory
+ )
+{
+ iv_target = i_target;
+ iv_dataBuffer = i_dataBuffer;
+ iv_base = i_base;
+ iv_size = i_size;
+ iv_permissions = i_permissions;
+ iv_memory = i_memory;
+ iv_next = NULL;
+}
+
+
+//-----------------------------------------------------------------------------
+//
+fapi::ReturnCode
+PibMemory::operation(Transaction& io_transaction)
+{
+ fapi::ReturnCode rc;
+ ModelError me;
+
+ if( io_transaction.iv_mode & ACCESS_MODE_READ )
+ {
+ me = iv_memory->read( (uint32_t)(io_transaction.iv_offset * TRANSACTION_SIZE_IN_BYTES), io_transaction.iv_data, TRANSACTION_SIZE_IN_BYTES );
+ if( me == ME_NOT_MAPPED_IN_MEMORY && iv_passThrough )
+ {
+ rc = getScom( io_transaction.iv_address, io_transaction.iv_data );
+ if( rc.ok() )
+ {
+ me = ME_SUCCESS;
+ }
+ else
+ {
+ me = ME_FAILURE;
+ }
+ }
+ }
+ else if( io_transaction.iv_mode & ACCESS_MODE_WRITE )
+ {
+ me = iv_memory->write( (uint32_t)(io_transaction.iv_offset * TRANSACTION_SIZE_IN_BYTES), io_transaction.iv_data, TRANSACTION_SIZE_IN_BYTES );
+ if( me == ME_NOT_MAPPED_IN_MEMORY && iv_passThrough )
+ {
+ rc = putScom( io_transaction.iv_address, io_transaction.iv_data );
+ if( rc.ok() )
+ {
+ me = ME_SUCCESS;
+ }
+ else
+ {
+ me = ME_FAILURE;
+ }
+ }
+ }
+ else
+ {
+ me = iv_memory->fetch( (uint32_t)(io_transaction.iv_offset * TRANSACTION_SIZE_IN_BYTES), io_transaction.iv_data, TRANSACTION_SIZE_IN_BYTES );
+ if( me == ME_NOT_MAPPED_IN_MEMORY && iv_passThrough )
+ {
+ rc = getScom( io_transaction.iv_address, io_transaction.iv_data );
+ if( rc.ok() )
+ {
+ me = ME_SUCCESS;
+ }
+ else
+ {
+ me = ME_FAILURE;
+ }
+ }
+ }
+
+ io_transaction.busError( me );
+
+ if( me == ME_SUCCESS )
+ {
+ rc = (uint32_t)0; // if read/write or getScom/putScom succeeded then set rc = 0
+ }
+
+ // if read/write failed then rc == 1 by default
+ // if read/write returned ME_NOT_MAPPED_IN_MEMORY && pass through true then rc == value returned from putScom or getScom
+
+ return rc;
+}
+
+
+//-----------------------------------------------------------------------------
+Memory::Memory() :
+ iv_images(0)
+{
+#if POREVE_STATISTICS
+ resetStatistics();
+#endif
+}
+
+//-----------------------------------------------------------------------------
+Memory::~Memory()
+{
+}
+
+//-----------------------------------------------------------------------------
+bool
+Memory::checkCrc()
+{
+ MemoryImage* mi = iv_images;
+ bool rc = true;
+
+ do{
+
+ if( mi->checkCrc() == false )
+ {
+ rc = false;
+ break;
+ }
+ mi = mi->iv_next;
+
+ }while( mi != iv_images );
+
+ return rc;
+}
+
+
+//-----------------------------------------------------------------------------
+ModelError
+Memory::read(
+ uint32_t i_offset,
+ uint64_t& o_data,
+ size_t i_size
+ )
+{
+ char* from_ptr;
+ char* to_ptr;
+ size_t cnt;
+ MemoryImage* mi;
+ ModelError me;
+ int mi_found;
+
+ o_data = 0; // Assure all bytes are cleared
+
+ me = ME_SUCCESS;
+ do{
+ if( iv_images == 0 )
+ {
+ me = ME_NOT_MAPPED_IN_MEMORY;
+ break;
+ }
+ mi = iv_images;
+ mi_found = 0;
+ do{
+
+ if( (i_offset >= mi->iv_base) && ((i_offset + i_size) <= (mi->iv_base + mi->iv_size) ) )
+ {
+ mi_found= 1;
+ iv_images = mi; // have the Memory always point to the last MemoryImage that was used
+ break; // we found a chunk of memory containing the transaction address
+ }
+ mi = mi->iv_next;
+
+ }while( mi != iv_images );
+
+ if( ! mi_found )
+ { // There was no MemoryImage that contained the transaction address
+ me = ME_NOT_MAPPED_IN_MEMORY;
+ break;
+ }
+
+ if( (mi->iv_permissions & ACCESS_MODE_READ ) == 0 )
+ { // The permissions over the memory block do not allow the mode being used by the transaction
+ me = ME_MEMORY_IMAGE_PERMISSION_DENIED;
+ break;
+ }
+
+ // Init the character pointer into the eprom image we are using.
+ from_ptr = (char*)mi->iv_image + (i_offset - mi->iv_base);
+
+ // Init the character pointer into the o_data buffer.
+ // Take care of Endianess by moving to one or the other end of the buffer as appropriate.
+#ifdef _BIG_ENDIAN
+ to_ptr = (char*)&o_data + (TRANSACTION_SIZE_IN_BYTES - i_size);
+#else
+ to_ptr = ((char*)&o_data + i_size -1);
+#endif
+
+ for( cnt = 0; cnt < i_size; cnt++ )
+ {
+ *to_ptr = *from_ptr++;
+
+ // Move the to pointer either forward or backward as appropriate for Endianess
+#ifdef _BIG_ENDIAN
+ to_ptr++;
+#else
+ to_ptr--;
+#endif
+ }
+
+ me = ME_SUCCESS;
+ break;
+ }while(1);
+
+#if POREVE_STATISTICS
+ iv_reads++;
+#endif
+
+ return me;
+}
+
+//-----------------------------------------------------------------------------
+ModelError
+Memory::fetch(
+ uint32_t i_offset,
+ uint64_t& o_data,
+ size_t i_size
+ )
+{
+ char* from_ptr;
+ char* to_ptr;
+ size_t cnt;
+ MemoryImage* mi;
+ ModelError me;
+ int mi_found;
+
+ o_data = 0; // Assure all bytes are cleared
+
+ me = ME_SUCCESS;
+ do{
+ if( iv_images == 0 )
+ {
+ me = ME_NOT_MAPPED_IN_MEMORY;
+ break;
+ }
+ mi = iv_images;
+ mi_found = 0;
+ do{
+
+ if( (i_offset >= mi->iv_base) && ((i_offset + i_size) <= (mi->iv_base + mi->iv_size) ) )
+ {
+ mi_found= 1;
+ iv_images = mi; // have the Memory always point to the last MemoryImage that was used
+ break; // we found a chunk of memory containing the transaction address
+ }
+ mi = mi->iv_next;
+
+ }while( mi != iv_images );
+
+ if( ! mi_found )
+ { // There was no MemoryImage that contained the transaction address
+ me = ME_NOT_MAPPED_IN_MEMORY;
+ break;
+ }
+
+ if( (mi->iv_permissions & ACCESS_MODE_EXECUTE ) == 0 )
+ { // The permissions over the memory block do not allow the mode being used by the transaction
+ me = ME_MEMORY_IMAGE_PERMISSION_DENIED;
+ break;
+ }
+
+ // Init the character pointer into the eprom image we are using.
+ from_ptr = (char*)mi->iv_image + i_offset;
+
+ // Init the character pointer into the o_data buffer.
+ // Take care of Endianess by moving to one or the other end of the buffer as appropriate.
+#ifdef _BIG_ENDIAN
+ to_ptr = (char*)&o_data + (TRANSACTION_SIZE_IN_BYTES - i_size);
+#else
+ to_ptr = ((char*)&o_data + i_size -1);
+#endif
+
+ for( cnt = 0; cnt < i_size; cnt++ )
+ {
+ *to_ptr = *from_ptr++;
+
+ // Move the to pointer either forward or backward as appropriate for Endianess
+#ifdef _BIG_ENDIAN
+ to_ptr++;
+#else
+ to_ptr--;
+#endif
+ }
+
+ me = ME_SUCCESS;
+ break;
+ }while(1);
+
+#if POREVE_STATISTICS
+ iv_fetches++;
+#endif
+
+ return me;
+}
+
+
+
+//-----------------------------------------------------------------------------
+ModelError
+Memory::write(
+ uint32_t i_offset, // the address in the eprom image
+ uint64_t i_data, // data to write into the eprom image
+ size_t i_size // number of bytes to write (pretty much going to be TRANSACTION_SIZE_IN_BYTES)
+ )
+{
+ char* to_ptr;
+ char* from_ptr;
+ size_t cnt;
+ MemoryImage* mi;
+ ModelError me;
+ int mi_found;
+
+ me = ME_SUCCESS;
+ do{
+ if( iv_images == 0 )
+ {
+ me = ME_NOT_MAPPED_IN_MEMORY;
+ break;
+ }
+ mi = iv_images;
+ mi_found = 0;
+ do{
+
+ if( (i_offset >= mi->iv_base) && ((i_offset + i_size) <= (mi->iv_base + mi->iv_size) ) )
+ {
+ mi_found= 1;
+ iv_images = mi; // have the Memory always point to the last MemoryImage that was used
+ break; // we found a chunk of memory containing the transaction address
+ }
+ mi = mi->iv_next;
+
+ }while( mi != iv_images );
+
+ if( ! mi_found )
+ { // There was no MemoryImage that contained the transaction address
+ me = ME_NOT_MAPPED_IN_MEMORY;
+ break;
+ }
+
+ if( (mi->iv_permissions & ACCESS_MODE_WRITE ) == 0 )
+ { // The permissions over the memory block do not allow the mode being used by the transaction
+ me = ME_MEMORY_IMAGE_PERMISSION_DENIED;
+ break;
+ }
+
+ // Init the character pointer into the eprom image we are using.
+ to_ptr = (char*)mi->iv_image + i_offset;
+
+ // Init the character pointer into the o_data buffer.
+ // Take care of Endianess by moving to one or the other end of the buffer as appropriate.
+#ifdef _BIG_ENDIAN
+ from_ptr = (char*)&i_data + (TRANSACTION_SIZE_IN_BYTES - i_size);
+#else
+ from_ptr = ((char*)&i_data + i_size -1);
+#endif
+
+ for( cnt = 0; cnt < i_size; cnt++ )
+ {
+ *to_ptr++ = *from_ptr;
+
+ // Move the to pointer either forward or backward as appropriate for Endianess
+#ifdef _BIG_ENDIAN
+ from_ptr++;
+#else
+ from_ptr--;
+#endif
+ }
+
+ me = ME_SUCCESS;
+ break;
+
+ }while(1);
+
+#if POREVE_STATISTICS
+ iv_writes++;
+#endif
+
+ return me;
+}
+
+
+//-----------------------------------------------------------------------------
+ModelError
+Memory::map(
+ uint32_t i_base, // For direct memory this is the 0 based offset from the Slave iv_base
+ size_t i_size, // Size of this chunk of memory
+ int i_permissions,
+ void* i_image,
+ bool i_crcEnable
+ )
+{
+ ModelError me = ME_SUCCESS;
+ MemoryImage* n;
+ MemoryImage* mi = new MemoryImage( i_base, i_size, i_permissions, i_image, i_crcEnable );
+
+ if( iv_images == 0 )
+ {
+ iv_images = mi;
+ mi->iv_next = mi;
+ }else{
+ n = iv_images->iv_next;
+ while( n->iv_next != iv_images )
+ {
+ n = n->iv_next;
+ }
+ n->iv_next = mi;
+ mi->iv_next = iv_images;
+ }
+
+ return me;
+}
+
+
+//-----------------------------------------------------------------------------
+#if POREVE_STATISTICS
+void
+Memory::resetStatistics()
+{
+ iv_reads = 0;
+ iv_writes = 0;
+ iv_fetches = 0;
+}
+#endif // POREVE_STATISTICS
+
+
+//-----------------------------------------------------------------------------
+MemoryImage::MemoryImage(
+ uint32_t i_base,
+ size_t i_size,
+ int i_permissions,
+ void* i_image,
+ bool i_crcEnable
+ )
+{
+
+ iv_base = i_base;
+ iv_size = i_size;
+ iv_permissions = i_permissions;
+ iv_image = i_image;
+ iv_crcEnable = i_crcEnable;
+ iv_originalCrc = 0;
+ iv_next = NULL;
+
+ if( i_crcEnable )
+ {
+ iv_originalCrc = computeCrc();
+ }
+
+}
+
+//-----------------------------------------------------------------------------
+MemoryImage::~MemoryImage()
+{
+}
+
+//-----------------------------------------------------------------------------
+uint64_t
+MemoryImage::computeCrc()
+{
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+bool
+MemoryImage::checkCrc()
+{
+ bool result = true;
+
+ if( iv_crcEnable == true )
+ {
+ uint64_t current_crc = computeCrc();
+ if( current_crc != iv_originalCrc )
+ {
+ result = false;
+ }
+ }
+
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+OciMemory::OciMemory() :
+iv_memory(NULL), iv_passThrough(false)
+{
+}
+
+//-----------------------------------------------------------------------------
+OciMemory::~OciMemory()
+{
+}
+
+//-----------------------------------------------------------------------------
+void
+OciMemory::setPassThrough(const bool i_enable)
+{
+ iv_passThrough = i_enable;
+}
+
+//-----------------------------------------------------------------------------
+void
+OciMemory::configure(
+ fapi::Target* i_target,
+ ecmdDataBufferBase* i_dataBuffer,
+ uint32_t i_base,
+ uint64_t i_size,
+ int i_permissions,
+ Memory* i_memory
+ )
+{
+ iv_target = i_target;
+ iv_dataBuffer = i_dataBuffer;
+ iv_base = i_base;
+ iv_size = i_size;
+ iv_permissions = i_permissions;
+ iv_memory = i_memory;
+}
+
+
+
+//-----------------------------------------------------------------------------
+//
+fapi::ReturnCode
+OciMemory::operation(Transaction& io_transaction)
+{
+ fapi::ReturnCode rc;
+
+ ModelError me;
+
+ if( io_transaction.iv_mode & ACCESS_MODE_READ )
+ {
+ me = iv_memory->read( (uint32_t)io_transaction.iv_offset, io_transaction.iv_data, TRANSACTION_SIZE_IN_BYTES );
+ if( me == ME_NOT_MAPPED_IN_MEMORY && iv_passThrough )
+ {
+ rc = read( io_transaction.iv_address, io_transaction.iv_data );
+ if( rc.ok() )
+ {
+ me = ME_SUCCESS;
+ }
+ else
+ {
+ me = ME_FAILURE;
+ }
+ }
+ }
+ else
+ {
+ me = iv_memory->write( (uint32_t)io_transaction.iv_offset, io_transaction.iv_data, TRANSACTION_SIZE_IN_BYTES );
+ if( me == ME_NOT_MAPPED_IN_MEMORY && iv_passThrough )
+ {
+ rc = write( io_transaction.iv_address, io_transaction.iv_data );
+ if( rc.ok() )
+ {
+ me = ME_SUCCESS;
+ }
+ else
+ {
+ me = ME_FAILURE;
+ }
+ }
+ }
+
+ io_transaction.busError( me );
+
+ if( me == ME_SUCCESS )
+ {
+ rc = (uint32_t)0;
+ }
+
+ // if read/write failed then rc == 1 by default
+ // if read/write returned ME_NOT_MAPPED_IN_MEMORY && pass through true then
+ // rc == value returned from putScom or getScom
+
+ return rc;
+}
+
+//-----------------------------------------------------------------------------
+fapi::ReturnCode
+OciSlave::operation(Transaction& io_transaction)
+{
+ fapi::ReturnCode rc;
+ ModelError me;
+
+ if( io_transaction.iv_mode & ACCESS_MODE_READ )
+ {
+ rc = read( io_transaction.iv_address, io_transaction.iv_data );
+ }
+ else
+ {
+ rc = write( io_transaction.iv_address, io_transaction.iv_data );
+ }
+
+ if( rc.ok() )
+ {
+ me = ME_SUCCESS;
+ }
+ else
+ {
+ me = ME_FAILURE;
+ }
+
+ io_transaction.busError( me );
+
+ return rc;
+}
+
+//-----------------------------------------------------------------------------
+OciSlave::~OciSlave()
+{
+}
+
+//-----------------------------------------------------------------------------
+fapi::ReturnCode
+OciSlave::read(const uint32_t i_address, uint64_t& o_data)
+{
+ fapi::ReturnCode rc;
+ return rc;
+}
+
+//-----------------------------------------------------------------------------
+fapi::ReturnCode
+OciSlave::write(const uint32_t i_address, const uint64_t i_data)
+{
+ fapi::ReturnCode rc;
+ return rc;
+}
+
+//-----------------------------------------------------------------------------
+fapi::ReturnCode
+OciSlaveWritable::write(const uint32_t i_address, const uint64_t i_data)
+{
+
+ // For this model, print out a message to confirm a write has been written is all it needs.
+ FAPI_INF("OciSlaveWritable::write(0x%08x, 0x%016llx)",
+ i_address, i_data);
+ fapi::ReturnCode rc;
+ return rc;
+}
+
diff --git a/src/usr/pore/poreve/porevesrc/bus.H b/src/usr/pore/poreve/porevesrc/bus.H
new file mode 100644
index 000000000..6370bae84
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/bus.H
@@ -0,0 +1,661 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/bus.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_BUS_H
+#define __VSBE_BUS_H
+
+// $Id: bus.H,v 1.14 2011/12/16 21:47:59 bcbrock Exp $
+
+/// \file bus.H
+/// \brief PoreVe bus and base device models
+
+#include <fapi.H>
+#include "transaction.H"
+
+
+namespace vsbe
+{
+
+class Slave;
+class Memory;
+
+// Temporary FAPI return codes from getscom/putscom errors
+#define fapi_PCB_RESOURCE_BUSY 0x02014003
+#define fapi_PCB_OFFLINE_ERROR 0x02014005
+#define fapi_PCB_PARTIAL_ERROR 0x02014007
+#define fapi_PCB_ADDRESS_ERROR 0x02014009
+#define fapi_PCB_CLOCK_ERROR 0x0201400B
+#define fapi_PCB_PARITY_ERROR 0x0201400D
+#define fapi_PCB_TIMEOUT_ERROR 0x0201400F
+
+//-----------------------------------------------------------------------------
+/*!
+The Pore hardware engine is connected via PIB bus and OCI bus. The Bus object
+functions to group all entities on the bus. For example, the PIB has the ability
+to run put/getscom via the PibSlave, as well as access OTPROM memory via the
+PibMemory object and PNOR and SEEPROM via FastI2cMemory objects.
+*/
+/// All pore hardware bus transactions are submitted through a Bus object.
+class Bus
+{
+
+public:
+
+ Bus();
+ virtual ~Bus();
+
+ /*! Primary Slaves are searched first for a given Transaction Address */
+ /// Primary Slaves are a linked list of Slave based objects
+ void attachPrimarySlave(Slave* i_slave);
+
+ /*! If a Secondary slave cannot service the Transaction then the Transaction address
+ is not mapped on the bus at all. */
+ /// Secondary Slaves are searched only if a Primary Slave did not support the Transaction Address
+ void attachSecondarySlave(Slave* i_slave);
+
+ /*!
+ The PrimarySlaves attached to the bus are checked to find one that handles the
+ Transaction address. If no match, then the SecondarySlaves are checked. When a
+ Slave is found containing the address the Transaction::iv_offset is set to the
+ Transaction::iv_address - Slave::iv_base. The Slave operation method is then
+ executed.
+
+ The return code from the Slave is passed back and becomes the return code of the
+ Bus operation. The Transaction ModelError is set by the Slave and is passed back
+ as well.
+
+ @returns If any error occurs then the fapi::ReturnCode is not ok, and the
+ transaction ModelError indicates the kind of problem found.
+
+ @returns rc=1 and Transaction ModelError=ME_NOT_MAPPED_ON_BUS if neither Primary
+ nor Secondary Slaves have mapped the transaction address.
+
+ @returns rc=1 and Transaction ModelError=ME_BUS_SLAVE_PERMISSION_DENIED if the
+ transaction address is found on a Slave but the Slave permissions deny the
+ transaction mode.
+
+ @returns rc=1 and Transaction ModelError= some other Model Error codes if the
+ Slave operation fails.
+
+ @returns rc=0 and Transaction ModelError=ME_SUCCESS if the transaction was
+ successful.
+ */
+ /// The basic method called to get a bus transaction done.
+ fapi::ReturnCode operation(Transaction& io_transaction);
+
+
+protected:
+
+ /// Primary list of "attached" bus elements like PibMemory, OciMemory and so forth
+ Slave* iv_primarySlaves;
+
+ /// The Secondary list is used when the Primary list fails to contain a Transaction address
+ Slave* iv_secondarySlaves;
+
+};
+
+//-----------------------------------------------------------------------------
+/*!
+Any kind of object attached to a Bus must be based upon the Slave class.
+Each of the Bus devices must specify their base address, size, and permissions
+as well as target and dataBuffer to be used for bus transactions. All these attributes
+are defined by the base Slave class.
+*/
+/// The Slave object contains the common attributes of all bus devices.
+class Slave
+{
+public:
+
+ Slave();
+ virtual ~Slave();
+
+ /// Slave based objects must be configured before use.
+ virtual void configure(fapi::Target* i_target,
+ ecmdDataBufferBase *i_dataBuffer,
+ uint32_t i_base,
+ uint64_t i_size,
+ int i_permissions);
+
+ /*!
+ Notice that the operation is pure virtual in the Slave class. All derived bus attached
+ devices must define their own operation methods since they vary from one to the other.
+ */
+ /// The Slave class also defines the fundamental operation that a Bus can call.
+ virtual fapi::ReturnCode operation(Transaction& io_transaction) = 0; // the slave instance will implement
+
+ /*!
+ The iv_base address is specified in terms of the system, so for example it might be the first address
+ in a range beginning at 0x08000000 in the system memory, or it might be the first address in a range of
+ scom addresses in the system.
+ */
+ /// The Bus devices base address. A System memory address or scom address, not an offset.
+ uint32_t iv_base;
+
+ /// This specifies the number of bytes from the iv_base that this Bus device responds to.
+ uint64_t iv_size;
+
+ /*!
+ For example: ACCESS_MODE_READ | ACCESS_MODE_WRITE | ACCESS_MODE_EXECUTE
+ */
+ /// Establish the read/write/execute mode allowed upon this Bus device.
+ int iv_permissions;
+
+ /// Points to the next Slave in a linked list that the Bus::operation will search
+ Slave* iv_next;
+
+ /// A pointer to the fapi Target to be used when accessing this Bus device.
+ fapi::Target* iv_target;
+
+ /// A pointer to the fapi DataBuffer to be used when accessing this Bus device.
+ ecmdDataBufferBase* iv_dataBuffer;
+
+
+};
+
+
+//-----------------------------------------------------------------------------
+/*!
+The SCOM addresses of a system are defined by a call to configure to the PIB
+slave for the system. There is no mapping done since there is no memory manager
+involved. When the PIB bus manager is asked to perform an operation and if the
+Transaction iv_address falls into the address range of the SCOM's then the
+operation method for the Slave will be called, which will call the
+PibSlave::getScom/putScom implemnted with fapiGet/Putscom.
+*/
+/// Implements SCOM access to the system.
+class PibSlave : public Slave
+{
+public:
+
+ PibSlave();
+ virtual ~PibSlave();
+
+ /// Overriding Slave::operation
+ virtual fapi::ReturnCode operation(Transaction& io_transaction);
+
+protected:
+
+ /*!
+ The i_offset is an actual scom address that has not been changed to implement
+ "core reduction" as an eCMD address might for certain chiplets. The address is
+ the raw native SCOM address used by the hardware.
+
+ The calling Slave class object iv_target and iv_dataBuffer are used to perform
+ the operation.
+
+ @returns rc= the value returned by fapi::GetScom
+ */
+ /// PibSlave read calls fapi::GetScom
+ fapi::ReturnCode getScom(const uint32_t i_offset, uint64_t& o_data);
+
+ /*!
+ The i_offset is an actual scom address that has not been changed to implement
+ "core reduction" as an eCMD address might for certain chiplets. The address is
+ the raw native SCOM address used by the hardware.
+
+ The calling Slave class object iv_target and iv_dataBuffer are used to perform
+ the operation.
+
+ @returns rc= the value returned by fapi::PutScom
+ */
+ /// PibSlave write calls fapi::PutScom
+ fapi::ReturnCode putScom(const uint32_t i_offset, const uint64_t i_data);
+};
+
+//-----------------------------------------------------------------------------
+/*!
+This object has (virtual) methods to handle directly access memory.
+*/
+/// Methods Used to access OTPROM.
+class PibMemory : public PibSlave
+{
+public:
+
+ PibMemory();
+ virtual ~PibMemory();
+
+
+ /// Slave based objects must be configured before use.
+ virtual void configure(fapi::Target* i_target,
+ ecmdDataBufferBase *i_dataBuffer,
+ uint32_t i_base,
+ uint64_t i_size,
+ int i_permissions,
+ Memory* i_memory);
+
+ /*!
+ Pass-through mode is established with a true value. This mode means that if a
+ PibMemory address is NOT_MAPPED_IN_MEMORY then the address of a transaction is
+ passed-through to the PibSlave::getScom or PibSlave::putScom method for resolution.
+ */
+ /// Control the pass-through mode. True means pass-through mode is enabled.
+ void setPassThrough(const bool i_enable);
+
+ /*!
+ Bus::operation already made sure the Transaction address is within our chunk of
+ memory and has set the Transaction::iv_offset.
+
+ This operation accesses direct memory, like OTPROM.
+
+ Transactions give us addresses on 64bit , or 8 byte, boundries. The address
+ passed into Memory::read or write is calculated as the Transaction::iv_offset *
+ 8. So, as example, if the Transaction::_iv_address was 0x08000000 and the
+ PibMemory Slave::iv_base were configured to 0x08000000 then the
+ Transaction::iv_offset would be 0x00000000. That multiplied by 8 remains
+ 0x00000000. If the Transaction address were 0x08000001, then the Transaction
+ offset would be 0x00000001, and that multiplied by 8 would be 0x00000008, the
+ reall offset into the eprom image we will read or write from.
+
+ If a ACCESS_MODE_READ transaction is called for then the Memory::read method is
+ called passing the Transaction iv_offset to complete the operation. If Memory::read
+ returns ME_NOT_MAPPED_IN_MEMORY and if iv_passThrough is true then
+ PibSlave::getScom is called passing the Transaction iv_address.
+
+ If a ACCESS_MODE_READ transaction is called for then the Memory::write method is
+ called passing the Transaction iv_offset to complete the operation. If Memory::write
+ returns ME_NOT_MAPPED_IN_MEMORY and if iv_passThrough is true then
+ PibSlave::putScom is called passing the Transaction iv_address.
+
+ @returns rc=0 if transaction succeeded
+ @returns rc=1 if transaction failed and passThrough mode was not active
+ @returns rc!=0 if read/write failed and passThrough call to getScom/putScom also
+ failed. In this case the rc value is whatever getScom or putScom returns from
+ fapi.
+
+ */
+ /// Implement a PibMemory transaction. Called by the Bus::operation()
+ virtual fapi::ReturnCode operation(Transaction& io_transaction);
+
+protected:
+
+ /// Remember the pass-through mode setting
+ bool iv_passThrough;
+
+ /// Pointer to Memory manager storing a linked list of MemoryImage (s) "containing" mapped memory areas
+ Memory* iv_memory;
+
+};
+
+//-----------------------------------------------------------------------------
+/// Not sure what a OciSlave does yet
+class OciSlave : public Slave
+{
+public:
+
+ virtual ~OciSlave();
+
+ /*!
+ Bus::operation already made sure the Transaction address is within our chunk of
+ memory and has set the Transaction::iv_offset.
+
+ If a ACCESS_MODE_READ transaction is called for then the OciSlave::read method is
+ called passing the Transaction iv_address to complete the operation.
+
+ If a ACCESS_MODE_WRITE transaction is called for then the OciSlave::write method is
+ called passing the Transaction iv_address to complete the operation.
+
+ @returns rc=0 if transaction succeeded
+ @returns rc=1 if transaction failed
+
+ */
+ virtual fapi::ReturnCode operation(Transaction& io_transaction);
+
+protected:
+
+ /*!
+ Called by OciSlave::operation.
+ */
+ virtual fapi::ReturnCode read(const uint32_t i_address, uint64_t& o_data);
+
+ /*!
+ Called by OciSlave::operation.
+ */
+ virtual fapi::ReturnCode write(const uint32_t i_address, const uint64_t i_data);
+
+};
+
+//-----------------------------------------------------------------------------
+/// An OciSlave that accepts and simply swallows write transactions
+class OciSlaveWritable : public OciSlave
+{
+public:
+ virtual fapi::ReturnCode write(const uint32_t i_address, const uint64_t i_data);
+};
+
+//-----------------------------------------------------------------------------
+/// Methods Used to access Mainstore/SRAM
+class OciMemory : public OciSlave
+{
+public:
+
+ OciMemory();
+ virtual ~OciMemory();
+
+ /// Slave based objects must be configured before use.
+ virtual void configure(fapi::Target* i_target,
+ ecmdDataBufferBase *i_dataBuffer,
+ uint32_t i_base,
+ uint64_t i_size,
+ int i_permissions,
+ Memory* i_memory);
+
+ /*!
+ Bus::operation already made sure the Transaction address is within our chunk of
+ memory and has set the Transaction::iv_offset.
+
+ This operation accesses memory like Mainstore or SRAM memory.
+
+ Transactions to the OCI bus give us addresses on byte boundries. The offset
+ passed into Memory::read or write is therefore simply the
+ Transaction::iv_offset without modification.
+
+ If a ACCESS_MODE_READ transaction is called for then the Memory::read method is
+ called passing the Transaction iv_offset to complete the operation. If Memory::read
+ returns ME_NOT_MAPPED_IN_MEMORY and if iv_passThrough is true then
+ OciSlave::read is called passing the Transaction iv_address.
+
+ If a ACCESS_MODE_READ transaction is called for then the Memory::write method is
+ called passing the Transaction iv_offset to complete the operation. If Memory::write
+ returns ME_NOT_MAPPED_IN_MEMORY and if iv_passThrough is true then
+ OciSlave::write is called passing the Transaction iv_address.
+
+ @returns rc=0 if transaction succeeded
+ @returns rc=1 if transaction failed and passThrough mode was not active
+ @returns rc!=0 if read/write failed and passThrough call to OciSlave::read/write also
+ failed. In this case the rc value is whatever OciSlave::read or OciSlave::write returns.
+ */
+ /// Implement a OciMemory transaction. Called by the Bus::operation()
+ virtual fapi::ReturnCode operation(Transaction& io_transaction);
+
+ /*!
+ Pass-through mode is established with a true value. This mode means that if a
+ OciMemory address is NOT_MAPPED_IN_MEMORY then the address of a transaction is
+ passed-through to the OciSlave::read or OciSlave::write method for resolution.
+ */
+ /// Control the pass-through mode. True means pass-through mode is enabled.
+ void setPassThrough(const bool i_enable);
+
+ /// Pointer to Memory manager storing a linked list of MemoryImage (s) "containing" mapped memory areas
+ Memory *iv_memory;
+
+protected:
+
+ /// Remember the pass-through mode setting
+ bool iv_passThrough;
+};
+
+
+//-----------------------------------------------------------------------------
+/// Store details of a block of memory being managed by a Memory manager
+class MemoryImage
+{
+public:
+
+ /*!
+ A MemoryImage is used to store information about a portion of Memory that has been mapped.
+ It is created by the Memory::map method.
+
+ @param i_base A zero based offset from the Slave iv_base address
+ @param i_size Size of i_image in bytes
+ @param i_permissions The read/write/execute permissions over this block of memory
+ @param i_image A pointer to an allocated block of memory storing the content of the block of memory
+ @param i_crcEnable true or false indicating whether crc is to be calculated over the block of memory
+ */
+ MemoryImage(uint32_t i_base,
+ size_t i_size,
+ int i_permissions,
+ void* i_image,
+ bool i_crcEnable );
+
+ virtual ~MemoryImage();
+
+ /*!
+ When this method is called the crc of the associated MemoryImage is calculated
+ and compared to iv_originalCrc which was the crc value at the time that the
+ MemoryImage was mapped into the Memory.
+
+ @returns true if iv_originalCrc == the current crc of the MemoryImage or if crc
+ checking is not enabled for the MemoryImage.
+ @returns false if crc checking is enabled and the crc values do not match.
+ */
+ /// true if iv_originalCrc == current crc, or if iv_crcEnable == false
+ virtual bool checkCrc();
+
+ /// base address associated with iv_image in the system (not real address of iv_image)
+ uint32_t iv_base;
+
+ /// byte size of the block of memory pointed to by iv_image
+ size_t iv_size;
+
+ /// Access permissions over this block of memory (ACCESS_MODE_READ | ACCESS_MODE_WRITE | ACCESS_MODE_EXECUTE)
+ int iv_permissions;
+
+ /// Pointer to the chunk of memory a user has allocated and stored eprom image into
+ void* iv_image;
+
+ /// Remember if told to compute crc or not via i_crcEnable
+ bool iv_crcEnable;
+
+ /// Link to next MemoryImage in the Memory managers circular linked list
+ MemoryImage* iv_next;
+
+protected:
+
+ /// Method to calculate crc over iv_image
+ virtual uint64_t computeCrc();
+
+ /// If iv_crcEnable is true this is the calculated crc over iv_image at the time it was mapped into Memory
+ uint64_t iv_originalCrc;
+};
+
+//-----------------------------------------------------------------------------
+/// Contains one or many MemoryImages for a certain type of memory
+class Memory
+{
+public:
+
+ Memory();
+ virtual ~Memory();
+
+ /*!
+ The map method is used to register a pointer to a contiguous block of memory
+ that contains some part of an eeprom image, as well as to declare the offset
+ from the system base address, the size, and access permissions of that block of
+ memory.
+
+ The iv_images pointer of the Memory manager points to one or many MemoryImages.
+ Each time this map method is called a new MemoryImage object is created to
+ remember all the details about the i_image being passed in. The new MemoryImage
+ is placed into a circular linked list owned by the Memory manager.
+
+ The Memory manager is always associated with a particuliar kind of memory, like
+ PibMemory or OciMemory, so the i_image is some portion of PibMemory or
+ OciMemory. As an example, suppose OTPROM is 0x01000000 bytes in the system,
+ starting at address 0x80000000. Also suppose you have parts of the OTPROM from
+ 0x80000000 to 0x80000100 and from 0x80010000 to 0x80010500 in two image files
+ that you have read into program memory and you want to map into the OTPROM
+ Memory manager. When calling the configure method on the PibMemory you declare
+ OTPROM memory starts at 0x80000000 and has 0x01000000 bytes. Then you call map
+ on the PibMemory manager twice, first declaring an offset 0x00000000 for
+ 0x00000100 bytes, then again with offset 0x00010000 for 0x00000500 bytes.
+
+ @param i_base A zero based offset from the Slave iv_base address
+ @param i_size Size of i_image in bytes
+ @param i_permissions The read/write/execute permissions over this block of memory
+ @param i_image A pointer to an allocated block of memory storing the content of the block of memory
+ @param i_crcEnable true or false indicating whether crc is to be calculated over the block of memory
+ @returns ME_SUCCESS if all's well (currently that's all it can return)
+ */
+ /// Register a "chunk" of memory to the Memory manager
+ virtual ModelError map(uint32_t i_base,
+ size_t i_size,
+ int i_permissions,
+ void* i_image,
+ bool i_crcEnable);
+
+ /*!
+ This method runs through every MemoryImage checking its crc.
+
+ @returns true if all MemoryImage have the same crc as when they were originally mapped into Memory
+ @returns false if any MemoryImage has a crc that is different
+ */
+ /// Check if crc of all MemoryImages is still the same as when it was originally mapped into Memory
+ virtual bool checkCrc();
+
+ /*!
+ This method is used to read Direct Memory out of an eprom image. An offset from
+ the base of the eprom memory image is passed in for the access, along with the
+ number of bytes to read.
+
+ The memory storage may be split into more than one MemoryImage's that have been
+ mapped. This method runs through the circuliarly linked list of MemoryImage objects
+ looking for one that contains the block of memory being accessed.
+
+ Upon successfully finding a containing MemoryImage the Memory::iv_images is set
+ to point to the MemoryImage just found. This should speed up operation assuming
+ a large number of transactions might occur on contiguous blocks of memory.
+
+ The data are copied out of the MemoryImage::iv_image into the o_data buffer for
+ return. The Endianess of the host platform being used is considered as this
+ operation occurs. (It is assumed the MemoryImage::iv_image is stored in
+ BigEndian order.)
+
+ @returns If there is no MemoryImage that contains the block of memory requested
+ then ME_NOT_MAPPED_IN_MEMORY is returned.
+
+ @returns If the memory block is found within a MemoryImage but the
+ MemoryImage::iv_permissions do not permit ACCESS_MODE_READ then
+ ME_MEMORY_IMAGE_PERMISSION_DENIED is returned.
+
+ @returns ME_SUCCESS if all bytes of the memory requested are contained in the
+ MemoryImage and the permissions of the MemoryImage allow ACCESS_MODE_READ.
+
+ */
+ /// Used to find a MemoryImage from which to read data
+ virtual ModelError read(uint32_t i_offset,
+ uint64_t& o_data,
+ size_t i_size
+ );
+
+ /*!
+ This method is used to fetch instructions from Direct Memory out of an eprom
+ image. An offset from the base of the eprom memory image is passed in for the
+ access, along with the number of bytes to read.
+
+ The memory storage may be split into more than one MemoryImage's that have been
+ mapped. This method runs through the circuliarly linked list of MemoryImage objects
+ looking for one that contains the block of memory being accessed.
+
+ Upon successfully finding a containing MemoryImage the Memory::iv_images is set
+ to point to the MemoryImage just found. This should speed up operation assuming
+ a large number of transactions might occur on contiguous blocks of memory.
+
+ The data are copied out of the MemoryImage::iv_image into the o_data buffer for
+ return. The Endianess of the host platform being used is considered as this
+ operation occurs. (It is assumed the MemoryImage::iv_image is stored in
+ BigEndian order.)
+
+ @returns If there is no MemoryImage that contains the block of memory requested
+ then ME_NOT_MAPPED_IN_MEMORY is returned.
+
+ @returns If the memory block is found within a MemoryImage but the
+ MemoryImage::iv_permissions do not permit ACCESS_MODE_EXECUTE then
+ ME_MEMORY_IMAGE_PERMISSION_DENIED is returned.
+
+ @returns ME_SUCCESS if all bytes of the memory requested are contained in the
+ MemoryImage and the permissions of the MemoryImage allow ACCESS_MODE_EXECUTE.
+
+ */
+ /// Used to find a MemoryImage from which to fetch instructions
+ virtual ModelError fetch(uint32_t i_offset,
+ uint64_t& o_data,
+ size_t i_size
+ );
+
+ /*!
+ This method is used to write Direct Memory out of an eprom image. An offset from
+ the base of the eprom memory image is passed in for the access, along with the
+ number of bytes to write.
+
+ The memory storage may be split into more than one MemoryImage's that have been
+ mapped. This method runs through the circuliarly linked list of MemoryImage objects
+ looking for one that contains the block of memory being accessed.
+
+ Upon successfully finding a containing MemoryImage the Memory::iv_images is set
+ to point to the MemoryImage just found. This should speed up operation assuming
+ a large number of transactions might occur on contiguous blocks of memory.
+
+ The data are copied out of the i_data buffer into the MemoryImage::iv_image. The
+ Endianess of the host platform being used is considered as this operation
+ occurs. (It is assumed the MemoryImage::iv_image is stored in BigEndian order.)
+
+ @returns If there is no MemoryImage that contains the block of memory requested
+ then ME_NOT_MAPPED_IN_MEMORY is returned.
+
+ @returns If the memory block is found within a MemoryImage but the
+ MemoryImage::iv_permissions do not permit ACCESS_MODE_WRITE then
+ ME_MEMORY_IMAGE_PERMISSION_DENIED is returned.
+
+ @returns ME_SUCCESS if all bytes of the memory requested are contained in the
+ MemoryImage and the permissions of the MemoryImage allow ACCESS_MODE_WRITE.
+
+ */
+ /// Used to find a MemoryImage to change
+ virtual ModelError write(uint32_t i_offset,
+ uint64_t i_data,
+ size_t i_size);
+
+ /// Pointer to first MemoryImage in a circularly linked list
+ MemoryImage* iv_images;
+
+#if POREVE_STATISTICS
+
+ /// Reset Memory usage statistics
+ ///
+ /// This API clears the instance variables iv_reads, iv_writes and
+ /// iv_fetches.
+ void
+ resetStatistics();
+
+ /// Number of read() calls for this memory
+ uint64_t iv_reads;
+
+ /// Number of write() calls for this memory
+ uint64_t iv_writes;
+
+ /// Number of fetch() calls for this memory
+ uint64_t iv_fetches;
+
+#endif // POREVE_STATISTICS
+
+};
+
+
+
+
+
+
+
+
+
+} // end of namespace vsbe
+#endif
diff --git a/src/usr/pore/poreve/porevesrc/create.C b/src/usr/pore/poreve/porevesrc/create.C
new file mode 100644
index 000000000..8e0d8d636
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/create.C
@@ -0,0 +1,46 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/create.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// $ID$
+
+/// \file create.C
+/// \brief The create method for PoreVe
+///
+/// The PoreVe class declares a static create() method that allows link-time
+/// selection of a normal vs. debug version of PoreVe. This is similar to the
+/// same idea used to make a link-time selection of the Pore hardware model
+/// (PMX vs. BOE). This create() method is linked into the poreve.so. The
+/// create() method for PoreVeDbg is defined in dbg.C
+
+#include "poreve.H"
+
+using namespace vsbe;
+
+PoreVe*
+PoreVe::create(const PoreIbufId i_id,
+ const fapi::Target i_masterTarget,
+ const void* i_arg)
+{
+ // i_arg is needed for subclass to instantiate and the (debug) subclass.
+ return new PoreVe(i_id, i_masterTarget);
+}
+
diff --git a/src/usr/pore/poreve/porevesrc/fasti2c.C b/src/usr/pore/poreve/porevesrc/fasti2c.C
new file mode 100644
index 000000000..676fdccda
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/fasti2c.C
@@ -0,0 +1,604 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/fasti2c.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// $Id: fasti2c.C,v 1.5 2012/01/10 00:27:41 bcbrock Exp $
+
+/// \file fasti2c.C
+/// \brief The "fast-mode" I2C controllers and I2C memory models used
+/// to implement the OTPROM, PNOR and SEEPROM interfaces.
+
+#include "fasti2c.H"
+
+/// Diagnostic aid for debugging fasti2c.C
+#ifdef DEBUG_FASTI2C
+#define BUG() \
+ FAPI_ERR("\n>>> fasti2c:Bug trapped at %s:%d\n\n", \
+ __FILE__, __LINE__)
+#else
+#define BUG()
+#endif // DEBUG_FASTI2C
+
+using namespace vsbe;
+
+////////////////////////////////////////////////////////////////////////////
+// I2cMemory
+////////////////////////////////////////////////////////////////////////////
+
+I2cMemory::I2cMemory(const size_t i_addressBytes) :
+iv_addressBytes(i_addressBytes), iv_address(0)
+{
+}
+
+
+I2cMemory::~I2cMemory()
+{
+}
+
+
+ModelError
+I2cMemory::addressWrite(const size_t i_bytes, const uint32_t i_address)
+{
+ ModelError me;
+
+ if (i_bytes != iv_addressBytes) {
+ BUG();
+ me = ME_I2CMEMORY_ILLEGAL_ADDRESS;
+ } else {
+ me = ME_SUCCESS;
+ iv_address = i_address;
+ }
+ return me;
+}
+
+
+ModelError
+I2cMemory::dataRead(const size_t i_bytes, uint64_t& o_data)
+{
+ ModelError me;
+
+ me = read(iv_address, o_data, i_bytes);
+ if (me == 0) {
+ iv_address += i_bytes;
+ }
+ return me;
+}
+
+
+ModelError
+I2cMemory::dataWrite(const size_t i_bytes, const uint64_t i_data)
+{
+ ModelError me;
+
+ me = write(iv_address, i_data, i_bytes);
+ if (me == 0) {
+ iv_address += i_bytes;
+ }
+ return me;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// FastI2cController
+////////////////////////////////////////////////////////////////////////////
+
+FastI2cController::FastI2cController() :
+ iv_devices(0),
+ iv_state(IDLE), iv_fifo(0)
+
+{
+ iv_status.value = 0;
+ iv_control.value = 0;
+}
+
+
+// The destructor deletes the circular list of devices.
+
+FastI2cController::~FastI2cController()
+{
+ I2cDevice *p, *next;
+
+ if (iv_devices != 0) {
+ for (p = iv_devices->next; p != iv_devices; p = next) {
+ next = p->next;
+ delete p;
+ }
+ delete iv_devices;
+ }
+}
+
+
+ModelError
+FastI2cController::attachMemory(I2cMemory* i_memory,
+ const unsigned i_port,
+ const unsigned i_deviceAddress)
+{
+ ModelError me = ME_SUCCESS;
+ FastI2cControlRegister control; // Used to validate i_Port and i_deviceId
+ I2cDevice* device = new I2cDevice;
+
+ control.fields.port_number = i_port;
+ control.fields.device_address = i_deviceAddress;
+ // Make sure input variables fits into control fields
+ if ((control.fields.port_number != i_port) ||
+ (control.fields.device_address != i_deviceAddress)) {
+ BUG();
+ me = ME_INVALID_ARGUMENT;
+
+ } else {
+
+ device->iv_port = i_port;
+ device->iv_deviceAddress = i_deviceAddress;
+ device->iv_memory = i_memory;
+
+ if (iv_devices == 0) {
+ iv_devices = device;
+ device->next = device;
+ } else {
+
+ if (findDevice(i_port, i_deviceAddress) != 0) {
+ BUG();
+ me = ME_DUPLICATE_CONFIGURATION;
+ } else {
+ device->next = iv_devices->next;
+ iv_devices->next = device;
+ }
+ }
+ }
+ if (me != 0) {
+ delete device;
+ }
+ return me;
+}
+
+
+// Modeling notes:
+//
+// o The RESET register is not modeled here
+//
+// o Our models ignore the I2C Speed
+//
+// o Transactions complete in 0 time and polling always succeeds on the first
+// read of the status register. This is done to simplify the PORE
+// engine model.
+//
+// o Only the following types of control register actions are modeled:
+// * Address write : with_start; with_address; !with_continue; with_stop;
+// data_length == 0
+// * Data read : with_start; with_address; !with_continue; with_stop;
+// data_length == [4,8]
+// * Data write : with_start; with_address; !with_continue; with_stop;
+// data_length == 8
+//
+// o The memory models hold the last address written
+//
+// o Redundant reads of the STATUS register are allowed
+//
+// o PORE only does 4/8 byte reads and 8 byte writes, so any other data
+// access is considered an error (although the models could easily be
+// extended to allow them).
+
+fapi::ReturnCode
+FastI2cController::operation(Transaction& io_transaction)
+{
+ ModelError me;
+ fapi::ReturnCode rc;
+
+ if (0) {
+ if (io_transaction.iv_mode == ACCESS_MODE_WRITE) {
+ FAPI_DBG("FASTI2C : write : offset = %u, data = 0x%016llx\n",
+ io_transaction.iv_offset,
+ io_transaction.iv_data);
+ } else {
+ FAPI_DBG("FASTI2C : read : offset = %u\n",
+ io_transaction.iv_offset);
+ }
+ }
+
+ switch (io_transaction.iv_offset) {
+
+ case FASTI2C_CONTROL_OFFSET:
+
+ if (io_transaction.iv_mode != ACCESS_MODE_WRITE) {
+ BUG();
+ me = ME_WRITE_ONLY_REGISTER;
+
+ } else if (iv_state != IDLE) {
+ BUG();
+ me = ME_FASTI2C_SEQUENCE_ERROR;
+
+ } else {
+
+ iv_control.value = io_transaction.iv_data;
+
+ if (!iv_control.fields.with_start ||
+ !iv_control.fields.with_address ||
+ iv_control.fields.read_continue ||
+ !iv_control.fields.with_stop) {
+ BUG();
+ me = ME_FASTI2C_CONTROL_ERROR;
+
+ } else if (iv_control.fields.read_not_write == 0) {
+
+ if (iv_control.fields.address_range == 0) {
+ BUG();
+ me = ME_FASTI2C_CONTROL_ERROR;
+
+ } else {
+ if (iv_control.fields.data_length == 0) {
+ me = addressWrite();
+
+ } else if (iv_control.fields.data_length != 8) {
+ BUG();
+ me = ME_FASTI2C_CONTROL_ERROR;
+
+ } else {
+ me = initialDataWrite();
+ }
+ }
+ } else {
+ if ((iv_control.fields.data_length != 4) &&
+ (iv_control.fields.data_length != 8)) {
+ BUG();
+ me = ME_FASTI2C_CONTROL_ERROR;
+ } else {
+ me = dataRead();
+ }
+ }
+ }
+ break;
+
+
+ case FASTI2C_STATUS_OFFSET:
+
+ if (io_transaction.iv_mode != ACCESS_MODE_READ) {
+ BUG();
+ me = ME_READ_ONLY_REGISTER;
+
+ } else {
+
+ switch (iv_state) {
+
+ case ADDRESS_WRITE_ONGOING:
+ case DATA_WRITE_ONGOING:
+ iv_status.value = 0;
+ iv_status.fields.i2c_command_complete = 1;
+ io_transaction.iv_data = iv_status.value;
+ iv_state = IDLE;
+ me = ME_SUCCESS;
+ break;
+
+ case DATA_READ_ONGOING:
+ iv_status.value = 0;
+ iv_status.fields.i2c_command_complete = 1;
+ iv_status.fields.i2c_fifo_entry_count =
+ iv_control.fields.data_length;
+ io_transaction.iv_data = iv_status.value;
+ iv_state = DATA_AVAILABLE;
+ me = ME_SUCCESS;
+ break;
+
+ case IDLE:
+ io_transaction.iv_data = iv_status.value;
+ me = ME_SUCCESS;
+ break;
+
+ default:
+ BUG();
+ me = ME_FASTI2C_SEQUENCE_ERROR;
+ break;
+ }
+ }
+ break;
+
+
+ case FASTI2C_DATA_OFFSET:
+
+ if ((io_transaction.iv_mode == ACCESS_MODE_READ) ||
+ (io_transaction.iv_mode == ACCESS_MODE_EXECUTE)) {
+
+ switch (iv_state) {
+
+ case DATA_AVAILABLE:
+ io_transaction.iv_data = iv_fifo;
+ iv_state = IDLE;
+ me = ME_SUCCESS;
+ break;
+
+ default:
+ BUG();
+ me = ME_FASTI2C_SEQUENCE_ERROR;
+ break;
+ }
+ } else {
+
+ switch (iv_state) {
+
+ case WRITE_DATA_EXPECTED:
+ me = finalDataWrite(io_transaction.iv_data);
+ iv_state = DATA_WRITE_ONGOING;
+
+ default:
+ BUG();
+ me = ME_FASTI2C_SEQUENCE_ERROR;
+ break;
+ }
+ }
+ break;
+
+
+ default:
+ BUG();
+ me = ME_ILLEGAL_REGISTER_OFFSET;
+ break;
+ }
+
+ if (me != 0) {
+ iv_state = ERROR;
+ rc = 1; // \bug Fix this
+ }
+ io_transaction.busError(me);
+ return rc;
+}
+
+
+// Find the device in the circular device list and spin the device to the
+// front of the list if found.
+
+I2cDevice*
+FastI2cController::findDevice(const unsigned i_port,
+ const unsigned i_deviceAddress)
+{
+ I2cDevice* p;
+
+ p = iv_devices;
+ if (p != 0) {
+ do {
+ if ((p->iv_port == i_port) &&
+ (p->iv_deviceAddress == i_deviceAddress)) {
+ iv_devices = p;
+ break;
+ }
+ if (p == iv_devices) {
+ p = 0;
+ break;
+ }
+ } while(1);
+ }
+ return p;
+}
+
+
+uint32_t
+FastI2cController::getI2cAddress(const FastI2cControlRegister i_control)
+{
+ size_t addressBytes = i_control.fields.address_range;
+
+ return i_control.words.low_order >> ((4 - addressBytes) * 8);
+}
+
+
+// The address is left-justified in the low-order 32 bits of the control
+// register.
+
+ModelError
+FastI2cController::addressWrite()
+{
+ ModelError me;
+ unsigned port = iv_control.fields.port_number;
+ unsigned deviceAddress = iv_control.fields.device_address;
+ size_t addressBytes = iv_control.fields.address_range;
+ I2cDevice* p;
+
+ p = findDevice(port, deviceAddress);
+ if (p == 0) {
+ BUG();
+ me = ME_NOT_MAPPED_ON_FASTI2C_CONTROLLER;
+ } else {
+ me = p->iv_memory->addressWrite(addressBytes,
+ getI2cAddress(iv_control));
+ iv_state = ADDRESS_WRITE_ONGOING;
+ }
+ return me;
+}
+
+
+ModelError
+FastI2cController::dataRead()
+{
+ ModelError me;
+ unsigned port = iv_control.fields.port_number;
+ unsigned deviceAddress = iv_control.fields.device_address;
+ size_t dataBytes = iv_control.fields.data_length;
+ uint64_t data;
+ I2cDevice* p;
+
+ p = findDevice(port, deviceAddress);
+ if (p == 0) {
+ BUG();
+ me = ME_NOT_MAPPED_ON_FASTI2C_CONTROLLER;
+ } else {
+ me = p->iv_memory->dataRead(dataBytes, data);
+ iv_fifo = data << (64 - (dataBytes * 8));
+ iv_state = DATA_READ_ONGOING;
+ }
+ return me;
+}
+
+
+// For addresses < 4 bytes, the first slug of data occupies the remainder of
+// the low-order word of the control register. Any remaining bytes come in on
+// the next transaction targeting the data register. This code assumes 8-byte
+// only data writes.
+
+ModelError
+FastI2cController::initialDataWrite()
+{
+ unsigned addressBytes = iv_control.fields.address_range;
+
+ if (addressBytes < 4) {
+ iv_fifo =
+ BE64_GET_FIELD(iv_control.words.low_order,
+ 32 + (addressBytes * 8),
+ 63) <<
+ ((4 - addressBytes) * 8);
+ }
+ iv_state = WRITE_DATA_EXPECTED;
+ return ME_SUCCESS;
+}
+
+
+// Assume 8-byte only write transactions
+
+ModelError
+FastI2cController::finalDataWrite(const uint64_t i_data)
+{
+ ModelError me;
+ unsigned port = iv_control.fields.port_number;
+ unsigned deviceAddress = iv_control.fields.device_address;
+ size_t addressBytes = iv_control.fields.address_range;
+ I2cDevice* p;
+
+ iv_fifo =
+ BE64_SET_FIELD(iv_fifo, addressBytes * 8, 63,
+ BE64_GET_FIELD(i_data, 0,
+ ((8 - addressBytes) * 8)) - 1);
+
+ p = findDevice(port, deviceAddress);
+ if (p == 0) {
+ BUG();
+ me = ME_NOT_MAPPED_ON_FASTI2C_CONTROLLER;
+ } else {
+ me = p->iv_memory->dataWrite(8, iv_fifo);
+ iv_state = DATA_WRITE_ONGOING;
+ }
+ return me;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// LpcController
+////////////////////////////////////////////////////////////////////////////
+
+LpcController::LpcController() :
+ iv_eccStart(0),
+ iv_eccStop(LPC_MEMORY_MAX_SIZE)
+{
+}
+
+
+LpcController::~LpcController()
+{
+}
+
+
+fapi::ReturnCode
+LpcController::operation(Transaction& io_transaction)
+{
+ ModelError me = ME_SUCCESS;
+ fapi::ReturnCode rc;
+ bool handledBySuperclass = false;
+ FastI2cControlRegister control;
+ uint32_t address;
+
+ switch (io_transaction.iv_offset) {
+
+ case LPCM_ECC_START_OFFSET:
+
+ if (iv_state != IDLE) {
+ BUG();
+ me = ME_FASTI2C_SEQUENCE_ERROR;
+
+ } else if (io_transaction.iv_mode == ACCESS_MODE_READ) {
+ io_transaction.iv_data = iv_eccStart;
+ me = ME_SUCCESS;
+
+ } else if (io_transaction.iv_mode == ACCESS_MODE_WRITE) {
+ iv_eccStart = io_transaction.iv_data;
+ me = ME_SUCCESS;
+
+ } else {
+ BUG();
+ me = ME_BUS_SLAVE_PERMISSION_DENIED;
+ }
+ break;
+
+ case LPCM_ECC_STOP_OFFSET:
+
+ if (iv_state != IDLE) {
+ BUG();
+ me = ME_FASTI2C_SEQUENCE_ERROR;
+
+ } else if (io_transaction.iv_mode == ACCESS_MODE_READ) {
+ io_transaction.iv_data = iv_eccStop;
+ me = ME_SUCCESS;
+
+ } else if (io_transaction.iv_mode == ACCESS_MODE_WRITE) {
+ iv_eccStop = io_transaction.iv_data;
+ me = ME_SUCCESS;
+
+ } else {
+ BUG();
+ me = ME_BUS_SLAVE_PERMISSION_DENIED;
+ }
+ break;
+
+ default:
+
+ if ((io_transaction.iv_offset == FASTI2C_CONTROL_OFFSET) &&
+ (io_transaction.iv_mode == ACCESS_MODE_WRITE)) {
+
+ control.value = io_transaction.iv_data;
+ address = getI2cAddress(control);
+ if ((address < iv_eccStart) || (address >= iv_eccStop)) {
+ BUG();
+ me = ME_LPC_ILLEGAL_ADDRESS;
+
+ } else {
+
+ handledBySuperclass = true;
+ rc = FastI2cController::operation(io_transaction);
+ }
+ } else {
+
+ handledBySuperclass = true;
+ rc = FastI2cController::operation(io_transaction);
+ }
+ break;
+ }
+ if (!handledBySuperclass) {
+ if (me != 0) {
+ rc = 1; // \bug Fix this;
+ }
+ io_transaction.busError(me);
+ }
+ return rc;
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/src/usr/pore/poreve/porevesrc/fasti2c.H b/src/usr/pore/poreve/porevesrc/fasti2c.H
new file mode 100644
index 000000000..a21288e94
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/fasti2c.H
@@ -0,0 +1,564 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/fasti2c.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_FASTI2C_H
+#define __VSBE_FASTI2C_H
+
+// $Id: fasti2c.H,v 1.5 2011/12/16 20:27:26 bcbrock Exp $
+
+/// \file fasti2c.H
+/// \brief The "fast-mode" I2C controllers and memory models used
+/// to implement the OTPROM, PNOR and SEEPROM interfaces.
+
+#include <fapi.H>
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "bebits.H"
+#include "bus.H"
+
+namespace vsbe {
+
+ class FastI2cController;
+ class LpcController;
+ class I2cMemory;
+
+ /// \defgroup fasti2c_speeds Fast-Mode I2C Controller Speeds
+ ///
+ /// Note that all speeds are considered "legal", and the model does not
+ /// interpret the speed setting.
+ ///
+ /// @{
+
+ const int FASTI2C_SPEED_100K = 0;
+ const int FASTI2C_SPEED_400K = 1;
+ const int FASTI2C_SPEED_3400K = 2;
+ const int FASTI2C_SPEED_50K = 3;
+
+ /// @}
+
+ /// \defgroup fasti2c_offsets Fast-Mode I2C Controller Register Offsets (PIB) and limits
+ ///
+ /// The last two offsets are only valid on the LpcController model.
+ /// @{
+
+ const uint32_t FASTI2C_CONTROL_OFFSET = 0x0;
+ const uint32_t FASTI2C_RESET_OFFSET = 0x1;
+ const uint32_t FASTI2C_STATUS_OFFSET = 0x2;
+ const uint32_t FASTI2C_DATA_OFFSET = 0x3;
+ const size_t FASTI2C_REGISTERS = 0x4;
+
+ const uint32_t LPCM_ECC_START_OFFSET = 0x4;
+ const uint32_t LPCM_ECC_STOP_OFFSET = 0x5;
+ const size_t LPCM_REGISTERS = 0x6;
+
+ /// @}
+
+ /// The maximum memory size supported by the LPC controller (64MB)
+ const uint32_t LPC_MEMORY_MAX_SIZE = (1 << 26);
+
+
+ // These register layouts are copied/modified from the PMX model. If they
+ // need to be modified here then they will also need to be modified in the
+ // PMX model.
+
+ /// Fast-Mode I2C Controller Control Register Layout
+ typedef union {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t with_start : 1;
+ uint64_t with_address : 1;
+ uint64_t read_continue : 1;
+ uint64_t with_stop : 1;
+ uint64_t data_length : 4;
+ uint64_t device_address : 7;
+ uint64_t read_not_write : 1;
+ uint64_t speed : 2;
+ uint64_t port_number : 5;
+ uint64_t address_range : 3;
+ uint64_t _reserved0 : 6;
+ uint64_t data0 : 8;
+ uint64_t data1 : 8;
+ uint64_t data2 : 8;
+ uint64_t data3 : 8;
+#else
+ uint64_t data3 : 8;
+ uint64_t data2 : 8;
+ uint64_t data1 : 8;
+ uint64_t data0 : 8;
+ uint64_t _reserved0 : 6;
+ uint64_t address_range : 3;
+ uint64_t port_number : 5;
+ uint64_t speed : 2;
+ uint64_t read_not_write : 1;
+ uint64_t device_address : 7;
+ uint64_t data_length : 4;
+ uint64_t with_stop : 1;
+ uint64_t read_continue : 1;
+ uint64_t with_address : 1;
+ uint64_t with_start : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+ } FastI2cControlRegister;
+
+
+ /// Fast-Mode I2C Controller Reset Register Layout
+ typedef union {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t value : 64;
+#else
+ uint64_t value : 64;
+#endif // _BIG_ENDIAN
+ } fields;
+ } FastI2cResetRegister;
+
+
+ /// Fast-Mode I2C Controller Status Register Layout
+ typedef union {
+
+ uint64_t value;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint32_t high_order;
+ uint32_t low_order;
+#else
+ uint32_t low_order;
+ uint32_t high_order;
+#endif // _BIG_ENDIAN
+ } words;
+ struct {
+#ifdef _BIG_ENDIAN
+ uint64_t pib_address_invalid : 1;
+ uint64_t pib_write_invalid : 1;
+ uint64_t pib_read_invalid : 1;
+ uint64_t pib_address_parity_error : 1;
+ uint64_t pib_parity_error : 1;
+ uint64_t lb_parity_error : 1;
+ uint64_t read_data : 32;
+ uint64_t _reserved0 : 6;
+ uint64_t i2c_macro_busy : 1;
+ uint64_t i2c_invalid_command : 1;
+ uint64_t i2c_parity_error : 1;
+ uint64_t i2c_back_end_overrun_error : 1;
+ uint64_t i2c_back_end_access_error : 1;
+ uint64_t i2c_arbitration_lost : 1;
+ uint64_t i2c_nack_received : 1;
+ uint64_t i2c_data_request : 1;
+ uint64_t i2c_command_complete : 1;
+ uint64_t i2c_stop_error : 1;
+ uint64_t i2c_port_busy : 1;
+ uint64_t i2c_interface_busy : 1;
+ uint64_t i2c_fifo_entry_count : 8;
+#else
+ uint64_t i2c_fifo_entry_count : 8;
+ uint64_t i2c_interface_busy : 1;
+ uint64_t i2c_port_busy : 1;
+ uint64_t i2c_stop_error : 1;
+ uint64_t i2c_command_complete : 1;
+ uint64_t i2c_data_request : 1;
+ uint64_t i2c_nack_received : 1;
+ uint64_t i2c_arbitration_lost : 1;
+ uint64_t i2c_back_end_access_error : 1;
+ uint64_t i2c_back_end_overrun_error : 1;
+ uint64_t i2c_parity_error : 1;
+ uint64_t i2c_invalid_command : 1;
+ uint64_t i2c_macro_busy : 1;
+ uint64_t _reserved0 : 6;
+ uint64_t read_data : 32;
+ uint64_t lb_parity_error : 1;
+ uint64_t pib_parity_error : 1;
+ uint64_t pib_address_parity_error : 1;
+ uint64_t pib_read_invalid : 1;
+ uint64_t pib_write_invalid : 1;
+ uint64_t pib_address_invalid : 1;
+#endif // _BIG_ENDIAN
+ } fields;
+ } FastI2cStatusRegister;
+
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// I2cMemory
+////////////////////////////////////////////////////////////////////////////
+
+
+/// An I2C memory model
+///
+/// The I2cMemory is a subclass of the Memory. It adds a device address for
+/// mapping onto an I2c bus, and also supports I2C memory operations such as
+/// addressWrite() and dataRead().
+
+class
+vsbe::I2cMemory : public Memory
+{
+
+public:
+
+ ////////////////////////////// Types //////////////////////////////
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ /// Create an I2c Memory
+ ///
+ /// \param[in] i_addressBytes The number of bytes (1-4) in a memory
+ /// address for this memory.
+ I2cMemory(const size_t i_addressBytes);
+
+ virtual ~I2cMemory();
+
+ ///////////////////////////// Accessors //////////////////////////////
+
+ //////////////////////////// Manipulators ////////////////////////////
+
+ /// Perform an I2C address write to an attached device.
+ ///
+ /// \param[in] i_bytes The number of address bytes, which must match the
+ /// configuration.
+ ///
+ /// \param[in] i_address The memory address.
+ ///
+ /// \retval me ModelError return code
+ ModelError
+ addressWrite(const size_t i_bytes, const uint32_t i_address);
+
+ /// Perform an I2C data read from an attached device.
+ ///
+ /// \param[in] i_bytes The number of data bytes to read
+ ///
+ /// \param[out] o_data The data, right justified
+ ///
+ /// The read has a side effect of incrementing the address held in the
+ /// device by \a i_bytes.
+ ///
+ /// \retval me ModelError return code
+ ModelError
+ dataRead(const size_t i_bytes, uint64_t& o_data);
+
+ /// Perform an I2C data write to an attached device.
+ ///
+ /// \param[in] i_bytes The number of data bytes to write
+ ///
+ /// \param[in] i_data The data, right justified
+ ///
+ /// The write has a side effect of incrementing the address held in the
+ /// device by \a i_bytes.
+ ///
+ /// \retval me ModelError return code
+ ModelError
+ dataWrite(const size_t i_bytes, const uint64_t i_data);
+
+
+ ////////////////////////// Implementation ////////////////////////////
+
+protected:
+
+ /// The number of address bytes (1-4)
+ const size_t iv_addressBytes;
+
+ /// The address register, auto-incremented on data reads and writes
+ uint32_t iv_address;
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ I2cMemory(const I2cMemory& i_rhs);
+ I2cMemory& operator=(const I2cMemory& i_rhs);
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// I2cDevice
+////////////////////////////////////////////////////////////////////////////
+
+namespace vsbe {
+
+/// A simple I2C device/bus model
+///
+/// This simple device/bus model is used by the FastI2cController to model the
+/// atachment of multiple I2cMemory to the physical busses (ports) controlled
+/// by each controller. Normally only 1 or two devices are attached to each
+/// controller so it's easiest to model all devices under control of a
+/// controller as a single list.
+
+typedef struct I2cDevice {
+
+ /// The controller port number - associated with a physical I2C bus
+ unsigned iv_port;
+
+ /// The device address of the device on the bus
+ unsigned iv_deviceAddress;
+
+ /// The I2cMemory
+ I2cMemory* iv_memory;
+
+ /// The next I2cdevice in the list of devices
+ struct I2cDevice* next;
+
+} I2cDevice;
+
+};
+
+////////////////////////////////////////////////////////////////////////////
+// FastI2cController
+////////////////////////////////////////////////////////////////////////////
+
+
+/// A model of a "fast-mode" I2C Controller
+///
+/// The PORE engine only uses the new "fast-mode" protocol to communicate with
+/// "I2C Controllers" that implement the physical memory interfaces for SBE
+/// memories. These controllers may be either real I2C controllers (like for
+/// SEEPROM) or pseudo-I2C-controllers like the PNOR and OTPROM controllers.
+/// The "fast-mode" is a new subset of the full I2C controller interface that
+/// only uses 4 registers. This model only models fast-mode accesses, and
+/// only in the precise way that PORE engines use fast-mode controllers for
+/// memory fetches, loads and stores. It will return errors for use of the
+/// legacy mode registers or otherwise legal sequences that are simply not
+/// modeled.
+///
+/// Each controller manages a number of "ports". Each port is a physical I2C
+/// bus, and devices attached to each port (bus) must have unique device IDs.
+/// We model the devices attached to a port independently. Each controller
+/// maintains a list of I2cDevice mapped to its ports. The underlying
+/// devices are currently all of the I2cMemory class.
+
+class
+vsbe::FastI2cController : public PibSlave
+{
+
+public:
+
+ ////////////////////////////// Types //////////////////////////////
+
+ /// \enum FastI2cState
+ ///
+ /// The state of the controller. Sequences of register operations are
+ /// only allowed in a prescribed sequence, depending on the state of the
+ /// controller. The ERROR state represents a bug in the model and is
+ /// non-recoverable.
+ enum FastI2cState {
+ ERROR,
+ IDLE,
+ ADDRESS_WRITE_ONGOING,
+ DATA_READ_ONGOING,
+ DATA_AVAILABLE,
+ WRITE_DATA_EXPECTED,
+ DATA_WRITE_ONGOING
+ };
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ FastI2cController();
+
+ virtual ~FastI2cController();
+
+ ///////////////////////////// Accessors //////////////////////////////
+
+ //////////////////////////// Manipulators ////////////////////////////
+
+ /// Attach a memory model to the controller
+ ///
+ /// \param[in] i_memory A configured I2cMemory
+ ///
+ /// \param[in] i_port The port (bus) number the memory is attached to
+ ///
+ /// \param[in] i_deviceAddress The device ID of the memory device on the bus
+ ///
+ /// \retval me Either 0 for success, ME_INVALID_ARGUMENT or
+ /// ME_AMBIGUOUS_CONFIGURATION.
+ ModelError
+ attachMemory(I2cMemory* i_memory,
+ const unsigned i_port,
+ const unsigned i_deviceAddress);
+
+ /// Handle a PIB transaction
+ ///
+ /// \param[in,out] io_transaction An abstract PIB transaction
+ ///
+ /// The FastI2cController is an indirect memory. In general several PIB
+ /// transactions are required to fetch a single doubleword of code or data
+ /// from the memory.
+ ///
+ /// \retval rc Either an "OK" return code for success, or a code
+ /// describing the error.
+ virtual fapi::ReturnCode
+ operation(Transaction& io_transaction);
+
+ ////////////////////////// Implementation ////////////////////////////
+
+protected:
+
+ /// Find a device in the list of devices attached to this controller
+ ///
+ /// \param[in] i_port The port number to search
+ ///
+ /// \param[in] i_deviceAddress The device address to search
+ ///
+ /// \retval device A pointer to the device if found, otherwise 0.
+ I2cDevice* findDevice(const unsigned i_port,
+ const unsigned i_deviceAddress);
+
+ /// Extract the I2C address from the CONTROL register
+ ///
+ /// \param[in] i_control The FastI2cControl register
+ ///
+ /// \retval address The indirect I2C address, taken from bytes 4-7 of the
+ /// control register depending on how many address bytes are indicated in
+ /// the control.
+ uint32_t getI2cAddress(const FastI2cControlRegister i_control);
+
+ /// Perform an I2C address write to an attached device.
+ ///
+ /// \retval me A ModelError return code in the event of errors, otherwise
+ /// 0.
+ ModelError addressWrite();
+
+ /// Perform an I2C data read from an attached device.
+ ///
+ /// \retval me A ModelError return code in the event of errors, otherwise
+ /// 0.
+ ModelError dataRead();
+
+ /// Begin an I2C data write an attached device.
+ ///
+ /// \retval me A ModelError return code in the event of errors, otherwise
+ /// 0.
+ ModelError initialDataWrite();
+
+ /// Finalize an I2C data write an attached device.
+ ///
+ /// \param[in] i_data The final bytes of a data write, left justtified.
+ ///
+ /// \retval me A ModelError return code in the event of errors, otherwise
+ /// 0.
+ ModelError finalDataWrite(const uint64_t i_data);
+
+ /// A list of I2cDevice, each of which is assigned to a controler port and
+ /// maintains a unique device ID for that port.
+ I2cDevice* iv_devices;
+
+ /// The abstract state of the controller
+ FastI2cState iv_state;
+
+ /// The last value written to the control register
+ FastI2cControlRegister iv_control;
+
+ /// The last value generated in the status register
+ FastI2cStatusRegister iv_status;
+
+ /// The data FIFO. Data is left-justified in this register.
+ uint64_t iv_fifo;
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ FastI2cController(const FastI2cController& i_rhs);
+ FastI2cController& operator=(const FastI2cController& i_rhs);
+};
+
+
+
+////////////////////////////////////////////////////////////////////////////
+// LpcController
+////////////////////////////////////////////////////////////////////////////
+
+/// Simplified model of the LPC controller as a fast-mode I2C controller
+///
+/// The LPC controller appears as a pseudo-FastI2cController with a couple of
+/// extra specializations. The fast-mode I2C controller specification
+/// is extended with two extra registers : The ECC start and stop
+/// addresses. We do not model ECC in our model, therefore this model only
+/// allows accesses that fall within the ECC window. The SBE will never
+/// address outside of the ECC window.
+
+class
+vsbe::LpcController : public FastI2cController
+{
+
+public:
+
+ ////////////////////////////// Types //////////////////////////////
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ LpcController();
+
+ virtual ~LpcController();
+
+ ///////////////////////////// Accessors //////////////////////////////
+
+ //////////////////////////// Manipulators ////////////////////////////
+
+ /// Handle a PIB transaction
+ ///
+ /// \param[in,out] io_transaction An abstract PIB transaction
+ ///
+ /// The LpcController is an indirect memory. In general several PIB
+ /// transactions are required to fetch a single doubleword of code or data
+ /// from the memory. The LpcController passes all transactions through to
+ /// the underlying FastI2cController except for reads/writes to the ECC
+ /// control registers. We require that any change to the ECC bounds be
+ /// made while the controller is in its IDLE state.
+ ///
+ /// \retval rc Either an "OK" return code for success, or a code
+ /// describing the error.
+ virtual fapi::ReturnCode
+ operation(Transaction& io_transaction);
+
+ ////////////////////////// Implementation ////////////////////////////
+
+protected:
+
+ /// The ECC start address register
+ uint64_t iv_eccStart;
+
+ /// The ECC stop address register
+ uint64_t iv_eccStop;
+};
+
+
+#endif // __VSBE_FASTI2C_H
diff --git a/src/usr/pore/poreve/porevesrc/hookmanager.C b/src/usr/pore/poreve/porevesrc/hookmanager.C
new file mode 100644
index 000000000..bf31e76b1
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/hookmanager.C
@@ -0,0 +1,575 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/hookmanager.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// $Id: hookmanager.C,v 1.12 2012/01/06 21:25:25 bcbrock Exp $
+
+/// \file hookmanager.C
+/// \brief A portable symbol table and hook execution facility
+
+#include <stdio.h>
+#include <string.h>
+
+#include "hookmanager.H"
+
+using namespace vsbe;
+
+
+#ifndef ULL
+/// The printf() checker for 64-bit GCC throws a warning if a uint64_t is
+/// printed as %llx - I have no idea why, but by casting them to (unsigned
+/// long long) the warning goes away.
+#define ULL(x) ((unsigned long long)(x))
+#endif
+
+fapi::ReturnCode vsbe::hookOk;
+HookManager* HookManager::s_instance = 0;
+
+
+////////////////////////////////////////////////////////////////////////////
+// CharPointerComparison
+////////////////////////////////////////////////////////////////////////////
+
+bool
+CharPointerComparison::operator()(char const* i_lhs,
+ char const* i_rhs) const
+{
+ return strcmp(i_lhs, i_rhs) < 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// HookManager
+////////////////////////////////////////////////////////////////////////////
+
+////////////////////////////// Creators //////////////////////////////
+
+HookManager::HookManager() :
+ iv_error(HOOK_OK)
+{
+}
+
+
+HookManager::~HookManager()
+{
+}
+
+
+///////////////////////////// Accessors //////////////////////////////
+
+fapi::ReturnCode
+HookManager::runInstructionHook(const PoreAddress& i_address,
+ const uint32_t i_hook,
+ const uint64_t i_parameter,
+ Pore& io_pore,
+ const fapi::Target& i_target)
+{
+ InstructionHookMap::iterator ihmi;
+ fapi::ReturnCode rc;
+
+ ihmi = instance()->iv_instructionHookMap.find(i_hook);
+ if (ihmi == instance()->iv_instructionHookMap.end()) {
+ rc = 0;
+ } else {
+ rc = (ihmi->second)(i_address, i_hook, i_parameter, io_pore, i_target);
+ }
+ return rc;
+}
+
+
+fapi::ReturnCode
+HookManager::runReadHooks(const PoreAddress& i_address,
+ Pore& io_pore,
+ const fapi::Target& i_target)
+
+{
+ return instance()->runHooks(HOOK_READ_INTERACTIVE, HOOK_READ_EXTRACTED,
+ i_address, io_pore, i_target);
+}
+
+
+fapi::ReturnCode
+HookManager::runWriteHooks(const PoreAddress& i_address,
+ Pore& io_pore,
+ const fapi::Target& i_target)
+{
+ return instance()->runHooks(HOOK_WRITE_INTERACTIVE, HOOK_WRITE_EXTRACTED,
+ i_address, io_pore, i_target);
+}
+
+
+fapi::ReturnCode
+HookManager::runFetchHooks(const PoreAddress& i_address,
+ Pore& io_pore,
+ const fapi::Target& i_target)
+{
+ return instance()->runHooks(HOOK_FETCH_INTERACTIVE, HOOK_FETCH_EXTRACTED,
+ i_address, io_pore, i_target);
+}
+
+
+HookError
+HookManager::findGlobalSymbol(const char* i_symbol,
+ bool& o_found,
+ GlobalSymbolInfo& io_info)
+{
+ GlobalSymbolMap::iterator gsmi;
+
+ o_found = false;
+ if (!instance()->iv_error) {
+ gsmi = instance()->iv_globalSymbolMap.find(i_symbol);
+ if (gsmi != instance()->iv_globalSymbolMap.end()) {
+ o_found = true;
+ io_info = *(gsmi->second);
+ }
+ }
+ return instance()->iv_error;
+}
+
+
+HookError
+HookManager::globalSymbolList(GlobalSymbolList& io_symbols, const char* i_types)
+{
+ GlobalSymbolMap::iterator gsmi;
+
+ if (!instance()->iv_error) {
+ for (gsmi = instance()->iv_globalSymbolMap.begin();
+ gsmi != instance()->iv_globalSymbolMap.end();
+ gsmi++) {
+
+ if ((i_types == 0) ||
+ (strchr(i_types, gsmi->second->iv_type) != 0)) {
+ io_symbols.push_back(*gsmi);
+ }
+ }
+ }
+ return instance()->iv_error;
+}
+
+
+void
+HookManager::report(const int i_options)
+{
+ InstructionHookMap::iterator ihmi;
+ HookedAddressMap::iterator hami;
+ HookedFileMap::iterator hfmi;
+ GlobalSymbolMap::iterator gsmi;
+ Hook* hook;
+ const HookTable* table;
+ size_t entry;
+ char type;
+ ExtractedHook* exHook;
+
+ if (i_options != 0) {
+
+ FAPI_INF("");
+ FAPI_INF("------------------------------------------------------");
+ FAPI_INF("-- HookManager @ %p", instance());
+ FAPI_INF("------------------------------------------------------");
+
+ if (i_options & HM_REPORT_HOOKED_ADDRESS_MAP) {
+
+ FAPI_INF("");
+ FAPI_INF("--- Hooked Address Map : %zu unique addresses ---",
+ instance()->iv_hookedAddressMap.size());
+ FAPI_INF("");
+
+ for (hami = instance()->iv_hookedAddressMap.begin();
+ hami != instance()->iv_hookedAddressMap.end();
+ hami++) {
+
+ for (hook = hami->second; hook != 0; hook = hook->iv_next) {
+ switch (hook->iv_type) {
+
+ case HOOK_READ_INTERACTIVE:
+ case HOOK_WRITE_INTERACTIVE:
+ case HOOK_FETCH_INTERACTIVE:
+ switch (hook->iv_type) {
+ case HOOK_READ_INTERACTIVE: type = 'r'; break;
+ case HOOK_WRITE_INTERACTIVE: type = 'w'; break;
+ case HOOK_FETCH_INTERACTIVE: type = 'x'; break;
+ default: type = '?'; break; // For GCC -Wall
+ }
+ FAPI_INF("%04x:%08x %c %p",
+ hami->first.iv_memorySpace,
+ hami->first.iv_offset,
+ type, hook->iv_hook);
+ break;
+
+ case HOOK_READ_EXTRACTED:
+ case HOOK_WRITE_EXTRACTED:
+ case HOOK_FETCH_EXTRACTED:
+ switch (hook->iv_type) {
+ case HOOK_READ_EXTRACTED: type = 'r'; break;
+ case HOOK_WRITE_EXTRACTED: type = 'w'; break;
+ case HOOK_FETCH_EXTRACTED: type = 'x'; break;
+ default: type = '?'; break; // For GCC -Wall
+ }
+ exHook = (ExtractedHook*)(hook->iv_hook);
+ FAPI_INF("%04x:%08x %8zu %s",
+ hami->first.iv_memorySpace, hami->first.iv_offset,
+ exHook->iv_index, exHook->iv_file);
+ break;
+
+ default: break; // For GCC -Wall
+ }
+ }
+ }
+ }
+
+ if (i_options & HM_REPORT_HOOK_TABLES) {
+
+ FAPI_INF("");
+ FAPI_INF("--- Hook Tables : %zu hooked files---",
+ instance()->iv_hookedFileMap.size());
+
+ for (hfmi = instance()->iv_hookedFileMap.begin();
+ hfmi != instance()->iv_hookedFileMap.end();
+ hfmi++) {
+
+ FAPI_INF("");
+ FAPI_INF("%s", hfmi->first);
+
+ table = hfmi->second;
+ for (entry = 0; entry < table->iv_entries; entry++) {
+ FAPI_INF("%8zu %p",
+ entry, table->iv_hooks[entry]);
+ }
+ }
+ }
+
+ if (i_options & HM_REPORT_INSTRUCTION_HOOK_MAP) {
+
+ FAPI_INF("");
+ FAPI_INF("--- Instruction Hook Map ---");
+ FAPI_INF("");
+
+ for (ihmi = instance()->iv_instructionHookMap.begin();
+ ihmi != instance()->iv_instructionHookMap.end();
+ ihmi++) {
+
+ FAPI_INF("%06x %p",
+ ihmi->first, ihmi->second);
+ }
+ }
+
+ if (i_options & HM_REPORT_GLOBAL_SYMBOL_MAP) {
+
+ FAPI_INF("");
+ FAPI_INF("--- Global Symbol Map ---");
+ FAPI_INF("");
+
+ for (gsmi = instance()->iv_globalSymbolMap.begin();
+ gsmi != instance()->iv_globalSymbolMap.end();
+ gsmi++) {
+
+ FAPI_INF("%04x:%08x %c %s",
+ gsmi->second->iv_address.iv_memorySpace,
+ gsmi->second->iv_address.iv_offset,
+ gsmi->second->iv_type,
+ gsmi->first);
+ }
+ }
+
+ FAPI_INF("");
+ FAPI_INF("------------------------------------------------------");
+ FAPI_INF("");
+ }
+}
+
+
+//////////////////////////// Manipulators ////////////////////////////
+
+HookError
+HookManager::registerInstructionHook(const uint32_t i_index,
+ HookInstructionHook i_hookRoutine)
+{
+ InstructionHookMap::iterator ihmi;
+
+ if (!instance()->iv_error) {
+
+ ihmi = instance()->iv_instructionHookMap.find(i_index);
+ if (ihmi == instance()->iv_instructionHookMap.end()) {
+
+ instance()->iv_instructionHookMap[i_index] = i_hookRoutine;
+
+ } else {
+ if (ihmi->second != i_hookRoutine) {
+ FAPI_ERR("%s : Static hook collision for index : %u",
+ __FUNCTION__, i_index);
+ instance()->iv_error = HOOK_STATIC_COLLISION;
+ }
+ }
+ }
+ return instance()->iv_error;
+}
+
+
+HookError
+HookManager::registerHookTable(const char* i_file,
+ const HookTable* i_table)
+{
+ if (!instance()->iv_error) {
+
+ if (instance()->iv_hookedFileMap.find(i_file) !=
+ instance()->iv_hookedFileMap.end()) {
+
+ FAPI_ERR("%s : File name collision : %s",
+ __FUNCTION__, i_file);
+ instance()->iv_error = HOOK_FILE_NAME_COLLISION;
+ } else {
+ instance()->iv_hookedFileMap[i_file] = i_table;
+ }
+ }
+ return instance()->iv_error;
+}
+
+
+HookError
+HookManager::registerHook(const PoreAddress& i_address,
+ Hook* io_hook)
+{
+ HookedAddressMap::iterator hami;
+ Hook* hook;
+
+ if (!instance()->iv_error) {
+
+ hami = instance()->iv_hookedAddressMap.find(i_address);
+ if (hami != instance()->iv_hookedAddressMap.end()) {
+ for (hook = hami->second;
+ hook->iv_next != 0;
+ hook = hook->iv_next);
+ hook->iv_next = io_hook;
+ } else {
+ instance()->iv_hookedAddressMap[i_address] = io_hook;
+ }
+ io_hook->iv_next = 0;
+ }
+ return instance()->iv_error;
+}
+
+
+HookError
+HookManager::registerGlobalSymbol(const char* i_symbol,
+ const GlobalSymbolInfo* i_info)
+{
+ if (!instance()->iv_error) {
+
+ if (instance()->iv_globalSymbolMap.find(i_symbol) !=
+ instance()->iv_globalSymbolMap.end()) {
+
+ FAPI_ERR("%s : Multiply defined symbol : %s",
+ __FUNCTION__, i_symbol);
+ instance()->iv_error = HOOK_MULTIPLY_DEFINED_SYMBOL;
+ } else {
+ instance()->iv_globalSymbolMap[i_symbol] = i_info;
+ }
+ }
+ return instance()->iv_error;
+}
+
+
+HookError
+HookManager::addInteractiveHook(const PoreAddress& i_address,
+ const HookType i_type,
+ const AddressBasedHook i_hookRoutine)
+{
+ Hook* hook = new Hook();
+ HookError rc;
+
+ instance()->iv_error = HOOK_OK;
+ if (hook == 0) {
+ rc = HOOK_MEMORY_ALLOCATION_FAILED;
+ } else {
+ switch (i_type) {
+ case HOOK_READ_INTERACTIVE:
+ case HOOK_WRITE_INTERACTIVE:
+ case HOOK_FETCH_INTERACTIVE:
+ rc = HOOK_OK;
+ hook->iv_type = i_type;
+ hook->iv_hook = (void*)i_hookRoutine;
+ registerHook(i_address, hook);
+ break;
+ default:
+ delete hook;
+ rc = HOOK_ILLEGAL_TYPE;
+ }
+ }
+ instance()->iv_error = rc;
+ return rc;
+}
+
+
+HookError
+HookManager::deleteInteractiveHooks(const PoreAddress& i_address,
+ const HookType i_type,
+ const AddressBasedHook i_hookRoutine)
+{
+ HookedAddressMap::iterator hami;
+ Hook **last, *hook, *next;
+ HookError rc;
+ bool deleted = false;
+
+ switch (i_type) {
+ case HOOK_READ_INTERACTIVE:
+ case HOOK_WRITE_INTERACTIVE:
+ case HOOK_FETCH_INTERACTIVE:
+
+ hami = instance()->iv_hookedAddressMap.find(i_address);
+ if (hami != instance()->iv_hookedAddressMap.end()) {
+ for (last = &(hami->second), hook = hami->second;
+ hook != 0;
+ hook = next) {
+ next = hook->iv_next;
+ if ((hook->iv_type == i_type) &&
+ ((i_hookRoutine == 0) ||
+ (hook->iv_hook) == i_hookRoutine)) {
+ delete hook;
+ deleted = true;
+ *last = next;
+ } else {
+ last = &(hook->iv_next);
+ }
+ }
+ }
+ if ((i_hookRoutine == 0) || deleted) {
+ if (hami->second == 0) {
+ instance()->iv_hookedAddressMap.erase(hami);
+ }
+ rc = HOOK_OK;
+ } else {
+ rc = HOOK_INTERACTIVE_DELETE_FAILED;
+ }
+ break;
+
+ default:
+ rc = HOOK_ILLEGAL_TYPE;
+ }
+ instance()->iv_error = rc;
+ return rc;
+}
+
+
+void
+HookManager::clearError()
+{
+ instance()->iv_error = HOOK_OK;
+}
+
+
+////////////////////////// Implementation ////////////////////////////
+
+fapi::ReturnCode
+HookManager::runHooks(const HookType i_interactiveType,
+ const HookType i_extractedType,
+ const PoreAddress& i_address,
+ Pore& io_pore,
+ const fapi::Target& i_target)
+{
+ HookedAddressMap::iterator hami;
+ Hook* hook;
+ ExtractedHook *exHook;
+ HookedFileMap::iterator hfmi;
+ const HookTable* table;
+ fapi::ReturnCode rc;
+
+ hami = instance()->iv_hookedAddressMap.find(i_address);
+ if (hami != instance()->iv_hookedAddressMap.end()) {
+
+ for (hook = hami->second;
+ (hook != 0) && rc.ok();
+ hook = hook->iv_next) {
+
+ if (hook->iv_type == i_interactiveType) {
+
+ rc = ((AddressBasedHook)(hook->iv_hook))(i_address,
+ i_interactiveType,
+ io_pore,
+ i_target);
+
+ } else if (hook->iv_type == i_extractedType) {
+
+ exHook = (ExtractedHook*)(hook->iv_hook);
+ hfmi = instance()->iv_hookedFileMap.find(exHook->iv_file);
+ if (hfmi == instance()->iv_hookedFileMap.end()) {
+
+ FAPI_ERR("%s : Address %04x:%08x is hooked from "
+ "file '%s', but no HookTable can be found "
+ "for the file.",
+ __FUNCTION__,
+ i_address.iv_memorySpace,
+ i_address.iv_offset,
+ exHook->iv_file);
+ instance()->iv_error = HOOK_TABLE_MISSING;
+ rc = 1; /// \todo Define this error
+
+ } else {
+
+ table = hfmi->second;
+ if (exHook->iv_index > table->iv_entries) {
+
+ FAPI_ERR("%s : Address %04x:%08x is hooked from "
+ "file '%s' at index %zu, "
+ "but the index exceeds "
+ "the number of hooks indexed for the "
+ "file (%zu).",
+ __FUNCTION__,
+ i_address.iv_memorySpace,
+ i_address.iv_offset,
+ hfmi->first, exHook->iv_index,
+ table->iv_entries);
+ instance()->iv_error = HOOK_INDEX_FAILURE;
+ rc = 1; /// \todo Define this error
+
+ } else {
+
+ rc =
+ (table->iv_hooks[exHook->iv_index])
+ (i_address, i_extractedType, io_pore, i_target);
+ }
+ }
+ } else {
+
+ FAPI_ERR("%s : Bug in HookManager - Unexpected type",
+ __FUNCTION__);
+ instance()->iv_error = HOOK_BUG;
+ rc = 1; /// \todo Define this error
+ }
+ if (!rc.ok()) break;
+ }
+ }
+ return rc;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// HookInitializer
+////////////////////////////////////////////////////////////////////////////
+
+HookInitializer::HookInitializer(HookManagerInitializer i_function)
+{
+ i_function();
+}
+
+
+HookInitializer::~HookInitializer()
+{
+}
diff --git a/src/usr/pore/poreve/porevesrc/hookmanager.H b/src/usr/pore/poreve/porevesrc/hookmanager.H
new file mode 100644
index 000000000..5323392c9
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/hookmanager.H
@@ -0,0 +1,859 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/hookmanager.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_HOOKMANAGER_H
+#define __VSBE_HOOKMANAGER_H
+
+// $Id: hookmanager.H,v 1.16 2012/01/06 21:25:25 bcbrock Exp $
+
+/// \file hookmanager.H
+/// \brief A portable symbol table and hook execution facility
+///
+/// Although the concept of a HookManager is generic, this implementation is
+/// specific to the FAPI PoreVe environment.
+///
+/// A hook is a C/C++ subroutine called during execution of the PoreVe. A
+/// hook is either associated with a HOOKI instruction, or with a particular
+/// PORE effective address. Address-based hooks are either read, write or
+/// fetch hooks, and may have either been installed interactively (e.g., by a
+/// debugger or hand-written code) or extracted from a source file. We make a
+/// distinction because extracted hooks are indexed via static tables created
+/// by processing an assembler source file, whereas interactive hooks are
+/// inserted individually. Extracted hooks are assumed to be characterized by
+/// permanent static data structures and can not be deleted. Interactive
+/// hooks can be created and deleted at will.
+///
+/// \todo Once the HBI use of the HookManager is finalized, it may be
+/// necessary to split this into 2 classes, one for HBI and another for Cronus
+/// verisons of PoreVe.
+///
+/// \todo Figure out if there is a way to make this more generic without having
+/// to use a template.
+
+#include <stdarg.h>
+#include <stdint.h>
+
+#include <list>
+#include <map>
+#include <utility>
+
+#include <fapi.H>
+
+#include "poremodel.H"
+
+namespace vsbe {
+
+ struct HookTable;
+ struct ExtractedHook;
+ struct Hook;
+ struct GlobalSymbolInfo;
+ class HookManager;
+ class HookInitializer;
+ class PoreAddress;
+ class PoreAddressComparison;
+ class CharPointerComparison;
+ class Pore;
+
+ /// An "OK" return code for use by hook routines
+ extern fapi::ReturnCode hookOk;
+
+ /// \enum HookType
+ ///
+ /// The type of a hook. See the comments for the file hookmanager.H.
+ enum HookType {
+ HOOK_INSTRUCTION,
+ HOOK_READ_INTERACTIVE,
+ HOOK_WRITE_INTERACTIVE,
+ HOOK_FETCH_INTERACTIVE,
+ HOOK_READ_EXTRACTED,
+ HOOK_WRITE_EXTRACTED,
+ HOOK_FETCH_EXTRACTED
+ };
+
+ /// The type of a HOOK instruction hook
+ ///
+ /// \param[in] i_address The effective address of the HOOK instruction
+ ///
+ /// \param[in] i_hook The low-order 24 bits of the HOOK instruction
+ ///
+ /// \param[in] i_Parameter A 64-bit parameter for the hook
+ ///
+ /// \param[in,out] io_pore The Pore model, to allow the hook to examine or
+ /// modify the state of the PORE.
+ ///
+ /// \param[in] i_target A reference to the FAPI Target currently
+ /// associated with the virtual PORE.
+ typedef fapi::ReturnCode
+ (*HookInstructionHook)(const PoreAddress& i_address,
+ const uint32_t i_hook,
+ const uint64_t i_parameter,
+ Pore& io_pore,
+ const fapi::Target& i_target);
+
+ /// The type of an address-based hook
+ ///
+ /// \param[in] i_address The effective address associated with the hook
+ ///
+ /// \param[in] i_type The type of the address-based hook
+ ///
+ /// \param[in,out] io_pore A reference to the Pore model, to allow the
+ /// hook to examine or modify the state of the PORE.
+ ///
+ /// \param[in] i_target A reference to the FAPI Target currently
+ /// associated with the virtual PORE.
+ typedef fapi::ReturnCode
+ (*AddressBasedHook)(const PoreAddress& i_address,
+ const HookType i_type,
+ Pore& io_pore,
+ const fapi::Target& i_target);
+
+ /// \enum HookError
+ ///
+ /// These error conditions are recognized both while the hook manager is
+ /// being initialized, and at run time. The last error code generated is
+ /// stored in the iv_error field of the HookManager.
+ enum HookError {
+ HOOK_OK = 0,
+ /// File name collision between hooked files
+ HOOK_FILE_NAME_COLLISION = 1,
+ /// Multiply defined symbol
+ HOOK_MULTIPLY_DEFINED_SYMBOL = 2,
+ /// A HookTable for a file is missing, suggesting hooks are out of
+ /// sync with the hooked sources
+ HOOK_TABLE_MISSING = 3,
+ /// Hook index too large, suggesting hooks are out of sync with the
+ /// hooked sources
+ HOOK_INDEX_FAILURE = 4,
+ /// An attempt was made to map more than one hook to a static hook
+ /// index.
+ HOOK_STATIC_COLLISION = 5,
+ /// Deprecated: An instruction hook was called for but not found
+ HOOK_INSTRUCTION_NOT_FOUND = 6,
+ /// An illegal HookType was specified for an API
+ HOOK_ILLEGAL_TYPE = 7,
+ /// Memory allocation failure for a new interactive hook
+ HOOK_MEMORY_ALLOCATION_FAILED = 8,
+ /// A request to delete a specific interactive hook failed
+ HOOK_INTERACTIVE_DELETE_FAILED = 9,
+ /// There is a bug in the HookManager
+ HOOK_BUG = 10,
+ };
+
+ /// \defgroup hookmanager_report_options HookManager Report Options
+ ///
+ /// By default, the HookManager::report() method prints all elements of
+ /// the report. An OR-combination of these flags can also be supplied as
+ /// the argument to explicitly specify that individual sections of the
+ /// report be printed.
+ ///
+ /// @{
+
+ /// Print the hooked address map
+ const int HM_REPORT_HOOKED_ADDRESS_MAP = 0x1;
+
+ /// Print the hook tables
+ const int HM_REPORT_HOOK_TABLES = 0x2;
+
+ /// Print the instruction hook map
+ const int HM_REPORT_INSTRUCTION_HOOK_MAP = 0x4;
+
+ /// Print the global symbol map
+ const int HM_REPORT_GLOBAL_SYMBOL_MAP = 0x8;
+
+ /// @}
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// HookTable
+////////////////////////////////////////////////////////////////////////////
+
+/// A table of AddressBasedHook function pointers associated with a source
+/// file.
+///
+/// These structures are created by the \e hook_extractor script as it
+/// processes the input to the assembler. Therefore the size of the \a
+/// iv_hooks table is constant and known at compile time. To save space the
+/// name of the file is not included here - instead the file name is the map
+/// key.
+
+struct
+vsbe::HookTable {
+
+ /// The number of hooks defined for the file
+ size_t iv_entries;
+
+ /// The table of addresses of the hook routines
+ AddressBasedHook *iv_hooks;
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// ExtractedHook
+////////////////////////////////////////////////////////////////////////////
+
+/// An index record for a hook extracted from a source file
+
+struct
+vsbe::ExtractedHook {
+
+ /// The file name of the hooked source file
+ const char* iv_file;
+
+ /// The index of the hook within the file
+ size_t iv_index;
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// Hook
+////////////////////////////////////////////////////////////////////////////
+
+/// A reference to a hook associated with a particular PORE address
+///
+/// The hook architecture allows multiple hooks to be associated with a single
+/// address. This situation could arise both by design and also by accident
+/// depending for example on conditional compilation or macro expansion. To
+/// support all of read, write and fetch hooks as well as static
+/// initialization of extracted hooks, this structure holds a generic hook
+/// pointer and a \a type field that indicates whether to interpret the
+/// pointer as a pointer to an ExtractedHook, or a direct pointer to an
+/// AddressBasedHook.
+
+struct
+vsbe::Hook {
+
+ /// The type of hook; See the enumeration HookType
+ HookType iv_type;
+
+ /// Either an AddressBasedHook or a pointer to an ExtractedHook, depending
+ /// on the HookType
+ void* iv_hook;
+
+ /// List linkage
+ struct Hook* iv_next;
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// GlobalSymbolInfo
+////////////////////////////////////////////////////////////////////////////
+
+/// Global Symbol Information
+///
+/// Global symbols are mapped by name. This structure includes the symbol
+/// address as a PoreAddress plus type information.
+
+struct
+vsbe::GlobalSymbolInfo {
+
+ /// The symbol address
+ PoreAddress iv_address;
+
+ /// The symbol type
+ ///
+ /// Symbol types are the character codes reported by \e nm:
+ ///
+ /// - \c B Global BSS (uninitialized data)
+ /// - \c C Global common (uninitialized data)
+ /// - \c D Global initialized data
+ /// - \c T Global text (code)
+ /// - \c R Global read only data
+ char iv_type;
+};
+
+
+namespace vsbe {
+ /// An STL list of <const char *, const GlobalSymbolInfo*> pairs
+ ///
+ /// This structure is defined for use in calls to
+ /// HookManager::globalSymbolList().
+ typedef std::list< std::pair<const char*, const GlobalSymbolInfo*> >
+ GlobalSymbolList;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreAddressComparison
+////////////////////////////////////////////////////////////////////////////
+
+/// PoreAddress comparison class
+///
+/// This class defines the comparison operator for STL containers using a
+/// PoreAddress as the key.
+
+////////////////////////////////////////////////////////////////////////////
+// CharPointerComparison
+////////////////////////////////////////////////////////////////////////////
+
+/// char* comparison class
+///
+/// This class defines the comparison operator for STL containers using a
+/// char* as the key.
+
+class
+vsbe::CharPointerComparison {
+
+public:
+
+ CharPointerComparison() {}
+
+ ~CharPointerComparison() {}
+
+ /// Compare CharPointer*
+ ///
+ /// \param[in] i_lhs Left hand side object
+ ///
+ /// \param[in] i_rhs Right hand side object
+ ///
+ /// \retval rc This is a simply strcmp(ilhs, irhs) < 0
+ bool operator() (char const* i_lhs,
+ char const* i_rhs) const;
+
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ // STL requires a copy operator
+ CharPointerComparison& operator=(const CharPointerComparison& rhs);
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// HookManager
+////////////////////////////////////////////////////////////////////////////
+
+/// A singleton class for managing code hooks for PORE VE
+///
+/// The hook manager is a portable C++ implementation of a symbol table for
+/// hook functions, hooked instructions and global symbols. Only one
+/// HookManager exists at any time. All methods are static and internally
+/// reference a singleton instance of a HookManager. The HookManager supports
+/// two main types of hooks:
+///
+/// - Pre-defined hooks associated with the PORE HOOKI instruction. The HOOKI
+/// instruction encodes an unsigned integer index of a hook routine to execute
+/// at that point, and also includes an uninterpreted 64-bit parameter. The
+/// mapping of hook indices to hook routines will likely be done
+/// statically. The HOOK instruction is otherwise a NOP.
+///
+/// - Address-based hooks are hooks that are attached to data loads and stores
+/// or instruction fetches. These hooks are normally attached by a scripting
+/// discipline that processes the input of the assembler to extract the hooks
+/// into a separate build and load path. Debugging environments can also add
+/// and delete hooks at run time.
+///
+/// The symbol table architecure and layout were designed to simplify the
+/// mapping and reduce space for the case that hooks are required during a
+/// space-constrained HBI procedure. Most symbol table data are defined as
+/// constants in the shared objects that initialize the hooks, and should
+/// never need to be copied.
+///
+/// The HookManager maintains 4 maps:
+///
+/// - A map that maps predefined hook indices encoded in HOOKI instructions to
+/// the routines that implement the hook. This map is created by calls of
+/// registerInstructionHook().
+///
+/// - A map that maps a source file name to a HookTable, that is table of
+/// function pointers to the routines that implement the hooks. This map is
+/// created by calls of registerHookTable().
+///
+/// - A map that maps a 48-bit \e effective PORE address to a list of Hook
+/// objects that identify the hook(s) associated with a PORE address. This map
+/// is created by calls of registerHook().
+///
+/// - A map that maps a PORE global symbol name to a pair <address, type>.
+/// This map is created by calls of registerGlobalSymbol().
+
+class
+vsbe::HookManager {
+
+public:
+
+ ////////////////////////////// Types //////////////////////////////
+
+ /// A map of HOOKI instruction indices to a HookInstructionHook
+ ///
+ /// This map is created by calls of registerInstructionHook(). The
+ /// application that provides the semantics of each HOOKI instruction
+ /// index will make these calls. The map is used by the
+ /// runInstructionHook() API to locate the entry point associated with a
+ /// HOOKI index.
+ typedef std::map<uint32_t, HookInstructionHook> InstructionHookMap;
+
+ /// A map of file names to hook routine tables
+ ///
+ /// This mapping is created by the *.hook.cc file that is generated by the
+ /// hook_extractor script for each file of assembler source code. Each
+ /// one of the *.hook.cc files maps the source code file name to a table
+ /// of entry points of the hooks extracted from that file. The
+ /// hook_indexer script references these tables to map hooked PORE
+ /// addresses to the entry point that implements the hook.
+ typedef std::map<const char*, const HookTable*> HookedFileMap;
+
+ /// A map of PORE addresses to lists of hooks
+ ///
+ /// This map is created by the registerHook() API. For extracted hooks,
+ /// these calls are made from the *.hooks.cc file created by the
+ /// hook_indexer from the symbol table of the final link image. The
+ /// registerHook() API can also be called dynamically by advanced
+ /// applications like the PDBG debugger for PORE programs. This map is
+ /// referenced by the runHooks() API.
+ ///
+ /// \note The comparison operator being used here is '<' on the uint64_t
+ /// form of the PoreAddress.
+ typedef std::map<const PoreAddress, Hook*> HookedAddressMap;
+
+ /// A map of global symbol names to their parameters
+ ///
+ /// This map is created by calls of registerGlobalSymbol(), called from
+ /// the *.hooks.cc file created by the hook_indexer script. This mapping
+ /// allows the allows the application to find global symbol addresses
+ /// using the findGlobalSymbol() API.
+ typedef std::map<const char*, const GlobalSymbolInfo*,
+ CharPointerComparison> GlobalSymbolMap;
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ virtual ~HookManager();
+
+ ///////////////////////////// Accessors //////////////////////////////
+
+ /// Access the singleton instance
+ ///
+ /// This is a standard design pattern: If the static singleton instance of
+ /// the class already exists, return it. Otherwise create it first.
+ static HookManager* instance() {
+ if (s_instance == 0) {
+ s_instance = new HookManager();
+ }
+ return s_instance;
+ }
+
+ /// Run a hook assigned to a HOOKI instruction encoding
+ ///
+ /// \param[in] i_address The effective address of the HOOKI instruction.
+ ///
+ /// \param[in] i_hook The index of the hook to run, taken from the
+ /// low-order 24 bits of the HOOKI instruction.
+ ///
+ /// \param[in] i_parameter A 64-bit parameter for the hook.
+ ///
+ /// \param[in,out] io_pore A reference to the Pore object, to allow hooks
+ /// to examine or alter the PORE state.
+ ///
+ /// \param[in] i_target A reference to the FAPI Target currently
+ /// associated with the virtual PORE.
+ ///
+ /// \retval rc If there is a hook routine associated with the hook index
+ /// \a i_hook, then this is the FAPI return code returned by the hook,
+ /// otherwise an "ok" (0) FAPI return code. There is no requirememt that
+ /// a hook routine be present in the Hookmanager for any instruction hook
+ /// index.
+ static fapi::ReturnCode
+ runInstructionHook(const PoreAddress& i_address,
+ const uint32_t i_hook,
+ const uint64_t i_parameter,
+ Pore& io_pore,
+ const fapi::Target& i_target);
+
+ /// Run any hooks associated with a data read of an effective address
+ ///
+ /// \param[in] i_address The effective address of the data read
+ ///
+ /// \param[in,out] io_pore A reference to the Pore object, to allow hooks
+ /// to examine or alter the PORE state.
+ ///
+ /// \param[in] i_target A reference to the FAPI Target currently
+ /// associated with the virtual PORE.
+ ///
+ /// If supported by the environment this method will be called before
+ /// every data read to run any hooks associated with reading the address.
+ ///
+ /// \retval rc The FAPI return code returned by the first (if any)
+ /// hook routine to return a non-OK code, otherwise an OK return code.
+ static fapi::ReturnCode
+ runReadHooks(const PoreAddress& i_address,
+ Pore& io_pore,
+ const fapi::Target& i_target);
+
+ /// Run any hooks associated with a data write of an effective address
+ ///
+ /// \param[in] i_address The effective address of the data write
+ ///
+ /// \param[in,out] io_pore A pointer to the Pore object, to allow hooks to
+ /// examine or alter the PORE state.
+ ///
+ /// \param[in] i_target A reference to the FAPI Target currently
+ /// associated with the virtual PORE.
+ ///
+ /// \retval rc The FAPI return code returned by the first (if any)
+ /// hook routine to return a non-OK code, otherwise an OK return code.
+ static fapi::ReturnCode
+ runWriteHooks(const PoreAddress& i_address,
+ Pore& io_pore,
+ const fapi::Target& i_target);
+
+ /// Run any hooks associated with an instruction fetch of an effective
+ /// address
+ ///
+ /// \param[in] i_address The effective address of the instruction fetch
+ ///
+ /// \param[in,out] io_pore A pointer to the Pore object, to allow hooks to
+ /// examine or alter the PORE state.
+ ///
+ /// \param[in] i_target A reference to the FAPI Target currently
+ /// associated with the virtual PORE.
+ ///
+ /// If supported by the environment this method will be called before
+ /// every instruction fetch to run any hooks associated with executing the
+ /// address.
+ ///
+ /// \retval rc The FAPI return code returned by the first (if any)
+ /// hook routine to return a non-OK code, otherwise an OK return code.
+ static fapi::ReturnCode
+ runFetchHooks(const PoreAddress& i_address,
+ Pore& io_pore,
+ const fapi::Target& i_target);
+
+ /// Find a global symbol in the HookManager symbol table
+ ///
+ /// \param[in] i_symbol The global symbol name to search for
+ ///
+ /// \param[out] o_found Indicates whether the symbol was found
+ ///
+ /// \param[in,out] io_info If the symbol is was found, this
+ /// reference is modified to contain the symbol information, otherwise the
+ /// reference is not modified.
+ ///
+ /// \retval rc HookManager sticky error status; This method fails
+ /// immediately if HookManager error status is set at entry. To clear the
+ /// error status use clearError().
+ static HookError
+ findGlobalSymbol(const char* i_symbol,
+ bool& o_found,
+ GlobalSymbolInfo& io_info);
+
+ /// Update a list of GlobalSymbolInfo based on the current state
+ ///
+ /// \param[in,out] io_symbols This is a reference to an instance of
+ /// GlobalSymbolList, an STL list of <const char*, const GlobalSymbolInfo*>
+ /// pairs.
+ ///
+ /// \param[in] i_types This optional parameter is a 0-terminated character
+ /// string containing 0 or more character codes of symbol types. Only
+ /// symbols whose type code is an element of the string are appended to \a
+ /// io_symbols. If \a i_types is 0 (or defaulted) then all global symbols
+ /// are returned. It probably doesn't make sense to call
+ /// globalSymbolList() with \a i_types as "" since this call would have no
+ /// effect.
+ ///
+ /// This routine takes a reference to a GlobalSymbolList, and operates by
+ /// appending (using the STL list push_back() method) a pair consisting of
+ /// the symbol name string and a pointer to a GlobalSymbolInfo structure
+ /// for each global symbol currently stored in the Global Symbol Table
+ /// that matches the symbol type filter. Type filtering is described with
+ /// the \a i_types argument. Global symbols are appended to \a io_symbols
+ /// in the lexicographic order defined by strcmp() < 0 on the character
+ /// string symbol names (i.e., they come back sorted by name).
+ ///
+ /// globalSymbolList() only appends to the list passed as the \a
+ /// io_symbols reference. Use the STL list clear() method to clear the
+ /// list if necessary prior to calling globalSymbolList().
+ ///
+ /// \retval rc HookManager sticky error status; This method fails
+ /// immediately if HookManager error status is set at entry. To clear the
+ /// error status use clearError().
+ static HookError
+ globalSymbolList(GlobalSymbolList& io_symbols, const char* i_types = 0);
+
+ /// Report the HookManager state to the FAPI_INF() stream
+ ///
+ /// \param[in] i_options Options are selected as an OR-combination of the
+ /// options documented as \ref hookmanager_report_options. By default all
+ /// elements of the report are printed.
+ ///
+ /// \retval 0 Success
+ static void
+ report(const int i_options = -1);
+
+ //////////////////////////// Manipulators ////////////////////////////
+
+ /// Register a HOOKI instruction hook with the HookManager
+ ///
+ /// \param[in] i_index The hook index as it will be stored in the HOOKI
+ /// instruction.
+ ///
+ /// \param[in] i_hookRoutine The hook routine
+ ///
+ /// It is considered an immediate fatal error (HOOK_STATIC_COLLISION) if
+ /// an attempt is made to map a single index to different hooks. Although
+ /// the HookManager could be easily modified to support multiple static
+ /// hooks for a single index if required, the current thinking is that
+ /// this more likely represents an error in assigning hook indices rather
+ /// than a useful feature.
+ ///
+ /// \retval rc HookManager sticky error status; This method fails
+ /// immediately if HookManager error status is set. To clear the error
+ /// status use clearError().
+ static HookError
+ registerInstructionHook(const uint32_t i_index,
+ HookInstructionHook i_hookRoutine);
+
+ /// Register a hook table with the hook manager
+ ///
+ /// \param[in] i_file The file name associated with the HookTable. This
+ /// string is assumed to be a permanent static allocation and is not
+ /// copied or storage managed by the HookManager.
+ ///
+ /// \param[in] i_table A pointer to a HookTable structure. This structure
+ /// is assumed to be a permanent static allocation and is not copied or
+ /// storage managed by the HookManager.
+ ///
+ /// The table is mapped by the hook manager based on the file name stored
+ /// in the table. It is considered an immediate fatal error
+ /// (HOOK_FILE_NAME_COLLISION) if a file name collision is detected.
+ ///
+ /// \retval rc HookManager sticky error status; This method fails
+ /// immediately if HookManager error status is set. To clear the error
+ /// status use clearError().
+ static HookError
+ registerHookTable(const char* i_file,
+ const HookTable* i_table);
+
+ /// Register an extracted Hook structure with the hook manager
+ ///
+ /// \param[in] i_address The effective address of a hooked
+ /// instruction.
+ ///
+ /// \param[in,out] io_hook An initialized Hook structure.
+ ///
+ /// This method is used directly by code generated from an extraction
+ /// script to install a hook for an address, due to the fact that
+ /// extracted hooks are initialized from preconstructed static objects.
+ /// This is also used as an internal method by addInteractiveHook().
+ ///
+ /// If more than one hook is associated with an address, later hooks are
+ /// added at the end of the list of hooks. When the hooks are run they
+ /// are run in list order.
+ ///
+ /// \retval rc HookManager sticky error status; This method fails
+ /// immediately if HookManager error status is set. To clear the error
+ /// status use clearError().
+ static HookError
+ registerHook(const PoreAddress& i_address,
+ Hook* io_hook);
+
+ /// Register a global symbol with the hook manager
+ ///
+ /// \param[in] i_symbol The symbol name. This string is assumed to be a
+ /// permanent static allocation and is not copied or storage managed by
+ /// the HookManager.
+ ///
+ /// \param[in] i_info Information about the symbol. This structure is
+ /// assumed to be a permanent static allocation and is not copied or
+ /// storage managed by the HookManager.
+ ///
+ /// For simplicity, it is considered an immediate fatal error
+ /// (HOOK_MULTIPLY_DEFINED_SYMBOL) to hook a symbol more than once. If we
+ /// need to provide similarly-named symbols in different address spaces
+ /// then we'll need to revisit the implementation.
+ ///
+ /// \retval rc HookManager sticky error status; This method fails
+ /// immediately if HookManager error status is set. To clear the error
+ /// status use clearError().
+ static HookError
+ registerGlobalSymbol(const char* i_symbol,
+ const GlobalSymbolInfo* i_info);
+
+ /// Add an interactive hook to a PoreAddress
+ ///
+ /// \param[in] i_address The effective address of the hooked
+ /// instruction or data.
+ ///
+ /// \param[in] i_type The hook type, which must be one of the *INTERACTIVE
+ /// types.
+ ///
+ /// \param[in] i_hookRoutine The AddressBasedHook that implements the hook.
+ ///
+ /// Create and install an interactive hook of \a i_type for an effective
+ /// PORE address. If more than one hook is associated with an address,
+ /// later hooks are added at the end of the list of hooks. When the hooks
+ /// are run they are run in list order.
+ ///
+ /// \retval rc A non-zero return value indicates any error that occurred.
+ /// This method fails immediately if HookManager error status is set at
+ /// entry. To clear the error status use clearError().
+ static HookError
+ addInteractiveHook(const PoreAddress& i_address,
+ const HookType i_type,
+ const AddressBasedHook i_hookRoutine);
+
+ /// Delete interactive hooks of a given type from a PoreAddress
+ ///
+ /// \param[in] i_address The effective address of the hooked
+ /// instruction or data.
+ ///
+ /// \param[in] i_type The hook type, which must be one of the *INTERACTIVE
+ /// types.
+ ///
+ /// \param[in] i_hookRoutine The AddressBasedHook that implements the
+ /// hook, or a default value of 0 which means to delete all interactive
+ /// hooks of the given type from the address.
+ ///
+ /// By default, delete all interactive hooks of \a i_type from an
+ /// effective PORE address. If \a i_hook is not 0, then all occurrences
+ /// of only that particular hook are deleted.
+ ///
+ /// \retval rc A non-zero return value indicates any error that occurred.
+ /// This method fails immediately if HookManager error status is set at
+ /// entry. To clear the error status use clearError().
+ static HookError
+ deleteInteractiveHooks(const PoreAddress& i_address,
+ const HookType i_type,
+ const AddressBasedHook i_hookRoutine = 0);
+
+ /// Clear the HookManager error status
+ ///
+ /// The HookManager has 'sticky' error status - new operations on the
+ /// HookManager will fail if the error status is non-zero. This method
+ /// clears the error status.
+ static void
+ clearError();
+
+ ////////////////////////// Implementation ////////////////////////////
+
+ /// The last HookError encountered
+ ///
+ /// Many of the HookError conditions arise during load-time
+ /// initialization, when there's really no recourse for trapping or
+ /// handling them. Instead, if the iv_error is non-0 then all load-time
+ /// HookManager APIs return immediately, allowing some diagnosis (of the
+ /// first error) after initialization. The interactive methods set and
+ /// return \a iv_error with the final return code but do not block further
+ /// operations.
+ HookError iv_error;
+
+ // NB: s_instance must be public for the Simics workaround
+
+ /// The singleton instance of the HookManager
+ static HookManager* s_instance;
+
+protected:
+
+ /// The instruction hook map
+ InstructionHookMap iv_instructionHookMap;
+
+ /// The hooked file map
+ HookedFileMap iv_hookedFileMap;
+
+ /// The hooked address map
+ ///
+ /// The HookManager system maintains an invariant that if an entry in this
+ /// map exists, then the list of hooks associated with that address is not
+ /// empty (i.e., the pointer is not 0).
+ HookedAddressMap iv_hookedAddressMap;
+
+ /// The global symbol map
+ GlobalSymbolMap iv_globalSymbolMap;
+
+ /// Run a specific type of hook
+ ///
+ /// \param[in] i_interactiveType One of the *INTERACTIVE HookType.
+ ///
+ /// \param[in] i_extractedType The *EXTRACTED counterpart of the
+ /// interactive type.
+ ///
+ /// \param[in] i_address The current effective address.
+ ///
+ /// \param[in,out] io_pore The Pore model, to allow the hook to examine or
+ /// modify the state of the PORE.
+ ///
+ /// \param[in] i_target A reference to the FAPI Target currently
+ /// associated with the virtual PORE.
+ ///
+ /// This is a helper method for runReadHooks(), runWriteHooks() and
+ /// runFetchHooks() that actually does the search and execution, given an
+ /// interactive and extracted hook type to search.
+ ///
+ /// \retval rc The FAPI return code returned by the first (if any)
+ /// hook routine to return a non-OK code, otherwise an OK return code.
+ fapi::ReturnCode
+ runHooks(const HookType i_interactiveType,
+ const HookType i_extractedType,
+ const PoreAddress& i_address,
+ Pore& io_pore,
+ const fapi::Target& i_target);
+
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ HookManager();
+ HookManager(const HookManager& i_rhs);
+ HookManager& operator=(const HookManager& i_rhs);
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// HookInitializer
+////////////////////////////////////////////////////////////////////////////
+
+/// A dummy class used to initialize the HookManager
+///
+/// Initialization of the HookManager depends on the ability of C++ to run
+/// object constructors at load time. Each hook file and indexing file
+/// contains an initialization function that installs information into the
+/// symbol table. Each hook file also creates an instance of the
+/// HookInitializer whose sole purpose is to run the initialization function
+/// in its constructor at load time.
+
+class
+vsbe::HookInitializer {
+
+public:
+
+ ////////////////////////////// Types //////////////////////////////
+
+ /// The type of a HookManager initializer function
+ typedef void (*HookManagerInitializer)();
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ /// Create an HookInitializer
+ ///
+ /// \param[in] i_function The function to call during construction of the
+ /// otherwise empty object.
+ HookInitializer(HookManagerInitializer i_function);
+
+ ~HookInitializer();
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ HookInitializer(const HookInitializer& rhs);
+ HookInitializer& operator=(const HookInitializer& rhs);
+};
+
+
+#endif // __VSBE_HOOKMANAGER_H
diff --git a/src/usr/pore/poreve/porevesrc/pib2cfam.C b/src/usr/pore/poreve/porevesrc/pib2cfam.C
new file mode 100644
index 000000000..cf6100767
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/pib2cfam.C
@@ -0,0 +1,167 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/pib2cfam.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// -*- mode: C++; c-file-style: "linux"; -*-
+// $Id: pib2cfam.C,v 1.9 2012/01/09 21:22:50 jeshua Exp $
+
+/// \file pib2cfam.C
+/// \brief A temporary hack while waiting for hardware updates - a simple
+/// PibSlave that maps a small range of PIB addresses to CFAM addresses.
+///
+/// \todo Verify the assumption that the high-order 32 bits of the 64-bit data
+/// are the bits that are read and written to the CFAM register.
+
+#include "pib2cfam.H"
+//JDS TODO - remove the ECMD headers once we've got attribute support
+#ifndef __HOSTBOOT_MODULE
+#include "fapiSharedUtils.H"
+#include "ecmdUtils.H"
+#endif
+using namespace vsbe;
+
+
+////////////////////////////// Creators //////////////////////////////
+
+Pib2Cfam::Pib2Cfam()
+{
+}
+
+
+Pib2Cfam::~Pib2Cfam()
+{
+}
+
+
+//////////////////////////// Manipulators ////////////////////////////
+
+static uint32_t
+translateAddress(uint32_t address, fapi::Target* i_target)
+{
+ //JDS TODO - change this to get attribute ATTR_FSI_GP_REG_SCOM_ACCESS
+ bool fsi_gpreg_scom_access = false;
+#ifndef __HOSTBOOT_MODULE
+ ecmdChipData chipdata;
+ ecmdChipTarget e_target;
+ uint32_t rc;
+ std::string chip_type;
+
+ fapiTargetToEcmdTarget( *i_target, e_target);
+ rc = ecmdGetChipData(e_target, chipdata);
+ if( rc ) printf( "Problem with getchipdata\n" );
+ chip_type = chipdata.chipType;
+
+ if( chip_type == "centaur" ) {
+ fsi_gpreg_scom_access = false;
+ } else {
+ fsi_gpreg_scom_access = true;
+ }
+#endif
+
+ if( fsi_gpreg_scom_access ) {
+ return (address - 0x00050000) + 0x2800;
+ } else {
+ return (address - 0x00050000) + 0x1000;
+ }
+}
+
+
+fapi::ReturnCode
+Pib2Cfam::operation(Transaction& io_transaction)
+{
+ fapi::ReturnCode rc;
+ ModelError me;
+
+ switch (io_transaction.iv_mode) {
+
+ case ACCESS_MODE_READ:
+
+ switch (io_transaction.iv_address) {
+
+ case 0x00050012:
+ case 0x00050013:
+ case 0x00050014:
+ case 0x00050015:
+ case 0x00050016:
+ case 0x00050019:
+ case 0x0005001A:
+ case 0x0005001B:
+ rc = fapiGetCfamRegister(*iv_target,
+ translateAddress(io_transaction.iv_address, iv_target),
+ *iv_dataBuffer);
+ if (rc.ok()) {
+ io_transaction.iv_data =
+ ((uint64_t)iv_dataBuffer->getWord(0)) << 32;
+ me = ME_SUCCESS;
+ } else {
+ me = ME_FAILURE;
+ }
+ break;
+ default:
+ me = ME_NOT_MAPPED_IN_MEMORY;
+ }
+ break;
+
+ case ACCESS_MODE_WRITE:
+
+ switch (io_transaction.iv_address) {
+
+ case 0x00050012:
+ case 0x00050013:
+ case 0x00050014:
+ case 0x00050015:
+ case 0x00050016:
+ case 0x0005001B:
+ iv_dataBuffer->setWordLength(1);
+ iv_dataBuffer->setWord(0, io_transaction.iv_data >> 32);
+ rc = fapiPutCfamRegister(*iv_target,
+ translateAddress(io_transaction.iv_address, iv_target),
+ *iv_dataBuffer);
+ if (rc.ok()) {
+ me = ME_SUCCESS;
+ } else {
+ me = ME_FAILURE;
+ }
+ break;
+
+ case 0x00050019:
+ case 0x0005001A:
+ rc = 1;
+ me = ME_BUS_SLAVE_PERMISSION_DENIED;
+ break;
+
+ default:
+ rc = 1;
+ me = ME_NOT_MAPPED_IN_MEMORY;
+ }
+ break;
+
+ default:
+ rc = 1;
+ me = ME_BUS_SLAVE_PERMISSION_DENIED;
+ break;
+ }
+ io_transaction.busError(me);
+ return rc;
+}
+/* Local Variables: */
+/* c-basic-offset: 4 */
+/* End: */
diff --git a/src/usr/pore/poreve/porevesrc/pib2cfam.H b/src/usr/pore/poreve/porevesrc/pib2cfam.H
new file mode 100644
index 000000000..329d3f0a3
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/pib2cfam.H
@@ -0,0 +1,94 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/pib2cfam.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_PIB2CFAM_H
+#define __VSBE_PIB2CFAM_H
+
+// $Id: pib2cfam.H,v 1.3 2011/06/21 00:07:35 bcbrock Exp $
+
+/// \file pib2cfam.H
+/// \brief A temporary hack while waiting for hardware updates - a simple
+/// PibSlave that maps a small range of PIB addresses to CFAM addresses.
+
+#include "bus.H"
+
+namespace vsbe {
+
+ class Pib2Cfam;
+
+ /// PIB base address of PIB range mapped by Pib2Cfam
+ const uint32_t PIB2CFAM_PIB_BASE = 0x00050012;
+
+ /// Number of PIB addresses mapped by Pib2Cfam
+ const int PIB2CFAM_PIB_SIZE = ((0x0005001b - 0x00050012) + 1);
+}
+
+
+/// Map PIB accesses to CFAM accesses
+
+class
+vsbe::Pib2Cfam : public PibSlave {
+
+public:
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ Pib2Cfam();
+
+ virtual ~Pib2Cfam();
+
+
+ //////////////////////////// Manipulators ////////////////////////////
+
+ /// Pib2Cfam operation
+ ///
+ /// \param[in,out] io_transaction A PIB transaction object
+ ///
+ /// This object converts PIB transactions in a certain range in the
+ /// virtual environment to FAPI PutCfamregister() and GetCfamRegister()
+ /// calls, returning the FAPI return code from the translated calls.
+ ///
+ /// The following PIB registers are mapped to CFAM registers:
+ ///
+ /// - PIB 0x00050012 -> CFAM 0x1012, FSIGP3, R/W
+ /// - PIB 0x00050013 -> CFAM 0x1013, FSIGP4, R/W
+ /// - PIB 0x00050014 -> CFAM 0x1014, FSIGP5, R/W
+ /// - PIB 0x00050015 -> CFAM 0x1015, FSIGP6, R/W
+ /// - PIB 0x00050016 -> CFAM 0x1016, FSIGP7, R/W
+ /// - PIB 0x00050019 -> CFAM 0x1019, OSC switch sense 1, R
+ /// - PIB 0x0005001A -> CFAM 0x101A, OSC switch sense 2, R
+ /// - PIB 0x0005001B -> CFAM 0x101B, GP3 Mirror, R/W
+ ///
+ /// \retval rc The fapi::ReturnCode returned by the underlying
+ /// PutCfamRegister() or GetCfamRegister() call.
+ fapi::ReturnCode
+ operation(Transaction& io_transaction);
+
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ Pib2Cfam(const Pib2Cfam& rhs);
+ Pib2Cfam& operator=(const Pib2Cfam& rhs);
+};
+
+#endif // __VSBE_PIB2CFAM_H
diff --git a/src/usr/pore/poreve/porevesrc/pore.C b/src/usr/pore/poreve/porevesrc/pore.C
new file mode 100644
index 000000000..8f09e2e29
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/pore.C
@@ -0,0 +1,269 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/pore.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// $Id: pore.C,v 1.13 2011/11/17 19:05:22 jeshua Exp $
+
+/// \file pore.C
+/// \brief The implementation of the PoreInterface for the PoreVe environment
+
+#include "pore.H"
+
+using namespace vsbe;
+
+
+///////////////////////// Control Interface /////////////////////////
+
+ModelError
+Pore::forceBranch(const char* i_symbol)
+{
+ ModelError me;
+ HookError he;
+ bool found;
+ GlobalSymbolInfo info;
+
+ he = HookManager::findGlobalSymbol(i_symbol, found, info);
+ if (he || !found) {
+ me = ME_ILLEGAL_FORCED_BRANCH;
+ } else {
+ me = PoreInterface::forceBranch(info.iv_address);
+ }
+ return me;
+}
+
+
+//////////////////// PoreInterface Methods /////////////////////////
+
+/// \bug We need a FAPI return code for an illegaly configured model
+
+void
+Pore::pibMaster(PibTransaction& io_transaction)
+{
+ ModelError me;
+
+ if (iv_pib == 0) {
+ me = ME_NO_BUS_MODEL;
+ io_transaction.busError(me);
+ iv_fapiReturnCode = 1; /// \bug Need a return code
+ } else {
+ iv_fapiReturnCode = iv_pib->operation(io_transaction);
+ me = io_transaction.iv_modelError;
+ }
+ if (me != 0) {
+ modelError(me);
+ }
+}
+
+
+void
+Pore::ociMaster(OciTransaction& io_transaction)
+{
+ ModelError me;
+
+ if (iv_oci == 0) {
+ me = ME_NO_BUS_MODEL;
+ io_transaction.busError(me);
+ iv_fapiReturnCode = 1; /// \bug Need a return code
+ } else {
+ iv_fapiReturnCode = iv_oci->operation(io_transaction);
+ me = io_transaction.iv_modelError;
+ }
+ if (me != 0) {
+ modelError(me);
+ }
+}
+
+
+void
+Pore::wait(const uint32_t i_count)
+{
+ uint64_t simCycles;
+ uint64_t nsDelay;
+ fapi::ReturnCode rc;
+ ModelError me;
+
+ nsDelay = (uint64_t)((i_count * 1e9) / PORE_FREQUENCY);
+
+ simCycles = (uint64_t)
+ (SIMULATOR_TICK_FREQUENCY * (i_count / PORE_FREQUENCY));
+ nsDelay += 1; // Always round up the real delay.
+ iv_fapiReturnCode = fapiDelay(nsDelay, simCycles);
+
+ if (iv_fapiReturnCode == 0) {
+ me = ME_SUCCESS;
+ } else {
+ me = ME_WAIT_FAILURE;
+ }
+ if (me != 0) {
+ modelError(me);
+ }
+}
+
+
+void
+Pore::hookInstruction(const PoreAddress& i_address,
+ const uint32_t i_hook,
+ const uint64_t i_parameter)
+{
+ ModelError me;
+
+ iv_fapiReturnCode =
+ HookManager::runInstructionHook(i_address, i_hook, i_parameter,
+ *this, *iv_target);
+ if (iv_fapiReturnCode.ok()) {
+ me = ME_SUCCESS;
+ } else {
+ me = ME_HOOK_INSTRUCTION_ERROR;
+ }
+ if (me != 0) {
+ modelError(me);
+ }
+}
+
+
+void
+Pore::hookRead(const PoreAddress& i_address)
+{
+ ModelError me;
+
+ iv_fapiReturnCode =
+ HookManager::runReadHooks(i_address, *this, *iv_target);
+ if (iv_fapiReturnCode.ok()) {
+ me = ME_SUCCESS;
+ } else {
+ me = ME_HOOK_READ_ERROR;
+ }
+ if (me != 0) {
+ modelError(me);
+ }
+}
+
+
+void
+Pore::hookWrite(const PoreAddress& i_address)
+{
+ ModelError me;
+
+ iv_fapiReturnCode =
+ HookManager::runWriteHooks(i_address, *this, *iv_target);
+ if (iv_fapiReturnCode.ok()) {
+ me = ME_SUCCESS;
+ } else {
+ me = ME_HOOK_WRITE_ERROR;
+ }
+ if (me != 0) {
+ modelError(me);
+ }
+}
+
+
+void
+Pore::hookFetch(const PoreAddress& i_address)
+{
+ ModelError me;
+
+ iv_fapiReturnCode =
+ HookManager::runFetchHooks(i_address, *this, *iv_target);
+ if (iv_fapiReturnCode.ok()) {
+ me = ME_SUCCESS;
+ } else {
+ me = ME_HOOK_FETCH_ERROR;
+ }
+ if (me != 0) {
+ modelError(me);
+ }
+}
+
+
+//////////////////////// PibSlave Methods ////////////////////////////
+
+// All offsets are known to be legal. PIB offsets are converted to OCI
+// offsets used in the register read/write methods.
+
+fapi::ReturnCode
+Pore::operation(Transaction& io_transaction)
+{
+ ModelError me;
+ fapi::ReturnCode rc;
+
+ switch (io_transaction.iv_mode) {
+
+ case ACCESS_MODE_READ:
+ me = registerRead((PoreRegisterOffset)(io_transaction.iv_offset * 8),
+ io_transaction.iv_data);
+ break;
+
+ case ACCESS_MODE_WRITE:
+ me = registerWrite((PoreRegisterOffset)(io_transaction.iv_offset * 8),
+ io_transaction.iv_data);
+ break;
+
+ default:
+ me = ME_BUS_SLAVE_PERMISSION_DENIED;
+ break;
+ }
+
+ if (me) {
+ rc = 1; /// \bug Fix this
+ }
+ io_transaction.busError(me);
+ return rc;
+}
+
+
+////////////////////////////// Creators //////////////////////////////
+
+Pore::Pore(PoreIbufId i_id) :
+ PoreInterface(i_id),
+ iv_pib(0),
+ iv_oci(0),
+ iv_target(NULL)
+{
+}
+
+
+Pore::~Pore()
+{
+}
+
+
+//////////////////// Interface Extensions /////////////////////////
+
+void
+Pore::configure(fapi::Target* i_target, Bus* i_pib, Bus* i_oci,
+ ecmdDataBufferBase* i_dataBuffer,
+ uint32_t i_base, uint64_t i_size, int i_permissions)
+{
+ iv_target = i_target;
+ iv_pib = i_pib;
+ iv_oci = i_oci;
+ PibSlave::configure(i_target, i_dataBuffer,
+ i_base, i_size, i_permissions);
+}
+
+
+fapi::ReturnCode
+Pore::getFapiReturnCode()
+{
+ return iv_fapiReturnCode;
+}
+
+
diff --git a/src/usr/pore/poreve/porevesrc/pore.H b/src/usr/pore/poreve/porevesrc/pore.H
new file mode 100644
index 000000000..7b773d0ad
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/pore.H
@@ -0,0 +1,259 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/pore.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_PORE_H
+#define __VSBE_PORE_H
+
+// $Id: pore.H,v 1.14 2011/11/17 19:04:47 jeshua Exp $
+
+/// \file pore.H
+/// \brief The implementation of the PoreInterface for the PoreVe environment
+
+#include <fapi.H>
+
+#include "bus.H"
+#include "poremodel.H"
+#include "hookmanager.H"
+
+ #ifdef VBU_HACKS
+ #include "fapiSharedUtils.H"
+ #include "ecmdUtils.H"
+ #endif // VBU_HACKS
+
+
+namespace vsbe {
+
+ class Pore;
+
+ /// This is the putative tick frequency of the simulation environment,
+ /// used to model the wait() method.
+ const double SIMULATOR_TICK_FREQUENCY = 12e9;
+
+ /// This is the expected operating frequency of the PORE hardware engine,
+ /// used to model the wait() method.
+ const double PORE_FREQUENCY = 600e6;
+};
+
+
+/// The implementation of the PoreInterface for the PoreVe environment
+///
+/// This class provides implementations of the virtual interface to the
+/// PoreModel for the PoreVe environment. The Pore is configured by providing
+/// pointers to the PIB and OCI bus models of the environment. The Pore also
+/// contains the last FAPI return code produced by an operation in the virtual
+/// environment.
+///
+/// The Pore class is also derived from the PibSlave class. This enables the
+/// PORE engine to 'self-SCOM' PORE control registers that are not visible as
+/// part of the architected state. Since our PoreVe environment does not
+/// included a generic OCB bridge, all self-SCOM must be programmed using PIB
+/// addresses.
+
+class
+vsbe::Pore : public PoreInterface,
+ public PibSlave
+{
+
+public:
+
+ ///////////////////////// Control Interface /////////////////////////
+
+ /// Force a branch to a global symbol name
+ ///
+ /// \param[in] i_symbol A global symbol name; the branch target
+ ///
+ /// Pore provides a variant of PoreModel::forceBranch() that forces a
+ /// branch to a global symbol, assuming the global symbol is known to
+ /// HookManager. The error code ME_ILLEGAL_FORCED_BRANCH is returned if
+ /// the symbol is not known to the HookManager.
+ ///
+ /// See PoreModel::forceBranch() for more information
+ ///
+ /// \retval me Either 0 for success or a ModelError code.
+ virtual ModelError
+ forceBranch(const char* i_symbol);
+
+
+ //////////////////// PoreInterface Methods /////////////////////////
+
+ /// See PoreModel::pibMaster() for the interface specification
+ ///
+ /// Run the transaction on the PoreVe PIB Bus model. FAPI errors from
+ /// running PIB/PCB transactions are converted to PCB return codes and
+ /// stored in the \a iv_pcbReturnCode field of the \a io_transaction.
+ void
+ pibMaster(PibTransaction& io_transaction);
+
+ /// See PoreModel::ociMaster() for the interface specification
+ ///
+ /// Run the transaction on the PoreVe OCI Bus model. FAPI errors from
+ /// running OCI transactions are converted to abstract return codes and
+ /// stored in the \a iv_ociReturnCode field of the \a io_transaction.
+
+ void
+ ociMaster(OciTransaction& io_transaction);
+
+ /// See PoreModel::wait() for the interface specification
+ ///
+ /// Simulate a WAIT of \a i_count PORE cycles. The implementation
+ /// attempts to accurately model the wait based on the assumed PORE clock
+ /// frequency, and for simulation, the assumed simulation clock frequency.
+ /// If execution of the WAIT results in a FAPI error, the FAPI error is
+ /// stored in the \a iv_fapiReturnCode.
+
+ void
+ wait(const uint32_t i_count);
+
+ /// See PoreModel::hookInstruction() for the interface specification
+ ///
+ /// Use the HookManager to run the numbered hook called out by a PORE
+ /// HOOKI instruction. It is not considered an error to request a hook
+ /// that is not mapped in the HookManager. If execution of the hook
+ /// results in a FAPI error, the FAPI error is stored in the
+ /// \a iv_fapiReturnCode.
+ void
+ hookInstruction(const PoreAddress& i_address,
+ const uint32_t i_hook,
+ const uint64_t i_parameter);
+
+ /// See PoreModel::hookRead() for the interface specification
+ ///
+ /// Run any hooks associated with a read of the given effective address.
+ /// If execution of the hook results in a FAPI error, the FAPI error is
+ /// stored in the \a iv_fapiReturnCode.
+ void
+ hookRead(const PoreAddress& i_address);
+
+ /// See PoreModel::hookWrite() for the interface specification
+ ///
+ /// Run any hooks associated with a write of the given effective address.
+ /// If execution of the hook results in a FAPI error, the FAPI error is
+ /// stored in the \a iv_fapiReturnCode.
+ void
+ hookWrite(const PoreAddress& i_address);
+
+ /// See PoreModel::hookFetch() for the interface specification
+ ///
+ /// Run any hooks associated with an instruction fetch of the given
+ /// effective address. If execution of the hook results in a FAPI error,
+ /// the FAPI error is stored in the \a iv_fapiReturnCode.
+ void
+ hookFetch(const PoreAddress& i_address);
+
+ /// See PoreModel::errorIntr() for the interface specification
+ ///
+ /// Currently not implemented by Pore.
+ void
+ errorIntr(void) {}
+
+ /// See PoreModel::fatalErrorIntr() for the interface specification
+ ///
+ /// Currently not implemented by Pore.
+ void
+ fatalErrorIntr(void) {}
+
+
+ //////////////////////// PibSlave Methods ////////////////////////////
+
+ /// See Slave::operation() for the interface specification
+ virtual fapi::ReturnCode
+ operation(Transaction& io_transaction);
+
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ /// Create the Pore
+ ///
+ /// \param[in] i_id The IBUF ID (PORE engine type) of the PORE model to
+ /// create.
+ Pore(PoreIbufId i_id);
+
+ virtual ~Pore();
+
+ //////////////////// Interface Extensions /////////////////////////
+
+ /// Configure the Pore model by providing pointers to the Bus models
+ ///
+ /// \param[in] i_target A pointer to the FAPI target object associated
+ /// with the PORE model, for use in hooks and for purposes of the
+ /// PibSlave.
+ ///
+ /// \param[in] i_pib A Bus model (to be) configured as a PIB bus.
+ ///
+ /// \param[in] i_oci A Bus model (to be) configured as an OCI bus.
+ ///
+ /// \param[in] i_dataBuffer See Slave::configure()
+ ///
+ /// \param[in] i_base See Slave::configure()
+ ///
+ /// \param[in] i_size See Slave::configure()
+ ///
+ /// \param[in] i_permissions See Slave::configure()
+ ///
+ /// This interface is introduced simply to encapsulate everything about
+ /// the Pore that needs to be configured to create a system.
+ void
+ configure(fapi::Target* i_target, Bus* i_pib, Bus* i_oci,
+ ecmdDataBufferBase* i_dataBuffer,
+ uint32_t i_base, uint64_t i_size, int i_permissions);
+
+ /// Get the FAPI return code from the model
+ ///
+ /// \retval rc The last FAPI return code from any PORE operations in the
+ /// environment.
+ fapi::ReturnCode
+ getFapiReturnCode();
+
+
+ ////////////////////////// Implementation ////////////////////////////
+
+protected:
+
+ /// The PoreVe PIB Bus model
+ Bus* iv_pib;
+
+ /// The PoreVe OCI Bus model
+ Bus* iv_oci;
+
+ /// The last FAPI return code
+ ///
+ /// Operations in the PoreVe environment return FAPI ReturnCode objects.
+ /// The FAPI return code is stored here, and the ModelError returned to
+ /// the PoreModel dependson the type of error.
+ fapi::ReturnCode iv_fapiReturnCode;
+
+ /// A pointer to the FAPI target associated with this PORE engine
+ ///
+ /// The Pore object holds this pointer for use as an argument to hook
+ /// routines.
+ fapi::Target* iv_target;
+
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+
+ Pore(const Pore& i_rhs);
+ Pore& operator=(const Pore& i_rhs);
+};
+
+#endif // __VSBE_PORE_H
diff --git a/src/usr/pore/poreve/porevesrc/poreve.C b/src/usr/pore/poreve/porevesrc/poreve.C
new file mode 100644
index 000000000..e0a841cdd
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/poreve.C
@@ -0,0 +1,480 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/poreve.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// $Id: poreve.C,v 1.15 2011/12/14 22:11:51 bcbrock Exp $
+
+/// \file poreve.C
+/// \brief The PORE Virtual Environment
+
+#include "poreve.H"
+
+using namespace vsbe;
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreVeBase
+////////////////////////////////////////////////////////////////////////////
+
+
+PoreVeBase::PoreVeBase(const PoreIbufId i_id,
+ const fapi::Target i_masterTarget) :
+ iv_pore(i_id),
+ iv_pnorMemory(PNOR_ADDRESS_BYTES),
+ iv_id(i_id),
+ iv_masterTarget(i_masterTarget),
+ iv_slaveTarget(i_masterTarget)
+{
+ uint32_t porePibBase;
+
+ // Configure the PORE. Only the PIB bus is connected, the OCI bus remains
+ // unconnected (0). The PIB self-SCOM interface configuration is a
+ // function of which PORE egine is being configured. Technically we should
+ // barf if \a i_id is not PORE_SBE or PORE_SLW, but HBI doesn't want any
+ // throw()s.
+
+ if (i_id == PORE_SLW) {
+ porePibBase = PORE_SLW_PIB_BASE;
+ } else {
+ porePibBase = PORE_SBE_PIB_BASE;
+ }
+
+ iv_pore.configure(&iv_slaveTarget, &iv_pib, 0,
+ &iv_dataBuffer,
+ porePibBase, PORE_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_pore);
+
+ // Configure the PNOR controller and attach its memory
+
+ iv_pnorController.configure(&iv_masterTarget,
+ &iv_dataBuffer,
+ PNOR_PIB_BASE,
+ PNOR_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_pnorController);
+
+ iv_pnorController.attachMemory(&iv_pnorMemory,
+ PNOR_I2C_PORT,
+ PNOR_I2C_DEVICE_ADDRESS);
+
+
+ // Configure the PIB catch-all model
+
+ iv_pibDefault.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ PIB_DEFAULT_PIB_BASE,
+ PIB_DEFAULT_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachSecondarySlave(&iv_pibDefault);
+}
+
+
+PoreVeBase::~PoreVeBase()
+{
+}
+
+
+// This is a temporary hack: Until the final specification of the reset state
+// of the PORE-SBE engine is available, we initialize the PORE-SBE engine
+// here. This is simpler than trying to keep the PMX model up to date as we
+// mess with chaging requirements, and it's also better for PMX to assume
+// that the PORE-SBE is halted at PMX-IPL, since PMX/Simics is really a model
+// for OCC firmware. This initializaton of PORE-SBE is done here rather than
+// in the PoreModel because we have the memory address assumptions here.
+//
+// If this is a PORE-SBE, then the machine comes up running from OTPROM.
+
+/// \bug Temporary hack
+
+void
+PoreVeBase::reset(fapi::Target i_slaveTarget)
+{
+ iv_slaveTarget = i_slaveTarget;
+ iv_pore.restart();
+ HookManager::clearError();
+
+ if (iv_id == PORE_SBE) {
+
+ // The PMX model comes up halted in OCI space. We set the PC to
+ // OTPROM space and run() 0 instructions. This will clear the stop bit
+ // to start execution.
+
+ PoreAddress pc;
+ uint64_t ran;
+
+ pc.setFromPibAddress(OTPROM_PIB_BASE);
+ iv_pore.setPc(pc);
+ iv_pore.run(0, ran);
+ }
+}
+
+
+int
+PoreVeBase::run(uint64_t i_instructions, uint64_t& o_ran)
+{
+ return iv_pore.run(i_instructions, o_ran);
+}
+
+
+ModelError
+PoreVeBase::getscom(const uint32_t i_address, uint64_t& o_data, int& o_rc)
+{
+ PibTransaction t;
+
+ t.iv_address = i_address;
+ t.iv_mode = ACCESS_MODE_READ;
+
+ iv_pib.operation(t);
+
+ o_data = t.iv_data;
+ o_rc = t.iv_pcbReturnCode;
+ return t.iv_modelError;
+}
+
+
+ModelError
+PoreVeBase::putscom(const uint32_t i_address, const uint64_t i_data, int& o_rc)
+{
+ PibTransaction t;
+
+ t.iv_address = i_address;
+ t.iv_data = i_data;
+ t.iv_mode = ACCESS_MODE_WRITE;
+
+ iv_pib.operation(t);
+
+ o_rc = t.iv_pcbReturnCode;
+ return t.iv_modelError;
+}
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreVe
+////////////////////////////////////////////////////////////////////////////
+
+PoreVe::PoreVe(const PoreIbufId i_id,
+ const fapi::Target i_masterTarget) :
+ PoreVeBase(i_id, i_masterTarget),
+ iv_seepromMemory(SEEPROM_ADDRESS_BYTES)
+{
+ uint32_t porePibBase;
+
+ // Reconfigure the Pore - this doesn't hurt anything in the previous
+ // configuration in the base class as this is a set of simple pointer and
+ // data assignments. But it's another reason to jettison the requirement
+ // for the base class. The PORE was attached to the PIB in the base
+ // class.
+
+ if (i_id == PORE_SLW) {
+ porePibBase = PORE_SLW_PIB_BASE;
+ } else {
+ porePibBase = PORE_SBE_PIB_BASE;
+ }
+
+ iv_pore.configure(&iv_slaveTarget, &iv_pib, &iv_oci,
+ &iv_dataBuffer,
+ porePibBase, PORE_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ // Configure the OTPROM
+
+ iv_otprom.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ OTPROM_PIB_BASE,
+ OTPROM_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_EXECUTE,
+ &iv_otpromMemory);
+
+ iv_pib.attachPrimarySlave(&iv_otprom);
+
+
+ // Configure the PIBMEM
+
+ iv_pibmem.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ PIBMEM_PIB_BASE,
+ PIBMEM_PIB_SIZE,
+ ACCESS_MODE_READ |
+ ACCESS_MODE_WRITE |
+ ACCESS_MODE_EXECUTE,
+ &iv_pibmemMemory);
+
+ iv_pib.attachPrimarySlave(&iv_pibmem);
+
+
+ // Configure the SEEPROM controller
+
+ iv_seepromController.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ SEEPROM_PIB_BASE,
+ SEEPROM_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_seepromController);
+
+ iv_seepromController.attachMemory(&iv_seepromMemory,
+ SEEPROM_I2C_PORT,
+ SEEPROM_I2C_DEVICE_ADDRESS);
+
+ // Configure Mainstore
+
+ iv_main.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ MAINSTORE_OCI_BASE,
+ MAINSTORE_OCI_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE,
+ &iv_mainMemory);
+
+ iv_oci.attachPrimarySlave(&iv_main);
+
+
+ // Configure SRAM
+
+ iv_sram.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ SRAM_OCI_BASE,
+ SRAM_OCI_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE,
+ &iv_sramMemory);
+
+ iv_oci.attachPrimarySlave(&iv_sram);
+
+
+#ifdef PM_HACKS
+ // This device provides write-only access to a single control register in
+ // the PMC.
+
+ iv_pmc.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ PMC_OCI_BASE,
+ PMC_OCI_SIZE,
+ ACCESS_MODE_WRITE);
+
+ iv_oci.attachPrimarySlave(&iv_pmc);
+#endif // PM_HACKS
+
+
+#ifdef VBU_HACKS
+ // Configure the temporary Pib2Cfam component
+
+ iv_pib2Cfam.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ PIB2CFAM_PIB_BASE,
+ PIB2CFAM_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_pib2Cfam);
+
+ // Configure the temporary sbeVital component
+
+ iv_sbeVital.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ SBEVITAL_PIB_BASE,
+ SBEVITAL_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_sbeVital);
+
+#ifndef SIMPLE_VBU_HACKS_ONLY
+
+ // The VBU_HACKS above are simple - they don't require complex eCMD support so
+ // we can test them easily with the poreve/test/fapistub test case.
+
+ // The VBU hacks below are complicated to emulate, so we don't even try in
+ // the test/fapistub test case.
+
+ // Configure the Broadside scan component if using BROADSIDE scan
+ //JDS TODO - add a check for broadside scan mode
+ ecmdConfigValid_t validOutput;
+ std::string tmpStr;
+ uint32_t tmpNum;
+ uint32_t rc;
+ ecmdChipTarget e_target;
+
+ //JDS TODO - change this to get attribute
+ fapiTargetToEcmdTarget( iv_slaveTarget, e_target);
+ rc = ecmdGetConfiguration(e_target, "SIM_BROADSIDE_MODE",
+ validOutput, tmpStr, tmpNum );
+ if( rc ||
+ validOutput == ECMD_CONFIG_VALID_FIELD_NONE ||
+ validOutput == ECMD_CONFIG_VALID_FIELD_NUMERIC )
+ {
+ FAPI_ERR( "Unable to determine SIM_BROADSIDE_MODE\n" );
+ }
+ else
+ {
+ size_t pos = tmpStr.find( "scan" );
+ if( pos != (uint32_t)-1 )
+ {
+// iv_bsscan_ex00.configure(&iv_slaveTarget,
+// &iv_dataBuffer,
+// BSSCAN_PIB_BASE | EX00_PIB_BASE,
+// BSSCAN_PIB_SIZE,
+// ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+// iv_pib.attachPrimarySlave(&iv_bsscan_ex00);
+
+ iv_bsscan_ex01.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX01_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex01);
+
+ iv_bsscan_ex02.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX02_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex02);
+
+ iv_bsscan_ex03.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX03_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex03);
+
+ iv_bsscan_ex04.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX04_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex04);
+
+ iv_bsscan_ex05.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX05_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex05);
+
+ iv_bsscan_ex06.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX06_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex06);
+
+// iv_bsscan_ex07.configure(&iv_slaveTarget,
+// &iv_dataBuffer,
+// BSSCAN_PIB_BASE | EX07_PIB_BASE,
+// BSSCAN_PIB_SIZE,
+// ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+// iv_pib.attachPrimarySlave(&iv_bsscan_ex07);
+
+// iv_bsscan_ex08.configure(&iv_slaveTarget,
+// &iv_dataBuffer,
+// BSSCAN_PIB_BASE | EX08_PIB_BASE,
+// BSSCAN_PIB_SIZE,
+// ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+// iv_pib.attachPrimarySlave(&iv_bsscan_ex08);
+
+ iv_bsscan_ex09.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX09_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex09);
+
+ iv_bsscan_ex10.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX10_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex10);
+
+ iv_bsscan_ex11.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX11_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex11);
+
+ iv_bsscan_ex12.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX12_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex12);
+
+ iv_bsscan_ex13.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX13_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex13);
+
+ iv_bsscan_ex14.configure(&iv_slaveTarget,
+ &iv_dataBuffer,
+ BSSCAN_PIB_BASE | EX14_PIB_BASE,
+ BSSCAN_PIB_SIZE,
+ ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+ iv_pib.attachPrimarySlave(&iv_bsscan_ex14);
+
+// iv_bsscan_ex15.configure(&iv_slaveTarget,
+// &iv_dataBuffer,
+// BSSCAN_PIB_BASE | EX15_PIB_BASE,
+// BSSCAN_PIB_SIZE,
+// ACCESS_MODE_READ | ACCESS_MODE_WRITE);
+
+// iv_pib.attachPrimarySlave(&iv_bsscan_ex15);
+ } //end SIM_BROADSIDE_MODE has scan
+ } //end was able to read SIM_BROADSIDE_MODE
+
+#endif // SIMPLE_VBU_HACKS_ONLY
+#endif // VBU_HACKS
+}
+
+
+PoreVe::~PoreVe()
+{
+}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/usr/pore/poreve/porevesrc/poreve.H b/src/usr/pore/poreve/porevesrc/poreve.H
new file mode 100644
index 000000000..4c2281940
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/poreve.H
@@ -0,0 +1,535 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/poreve.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_POREVE_H
+#define __VSBE_POREVE_H
+
+// $Id: poreve.H,v 1.18 2011/12/16 21:47:59 bcbrock Exp $
+
+/// \file poreve.H
+/// \brief The PORE Virtual Environment
+///
+/// The PORE Virtual Environment is a container class that contains a Pore
+/// model along with the Bus and Memory models that comprise a Pore system.
+/// These system models offer very little in the way of interfaces other than
+/// a way to reset() the simulation and a run() method to clock the
+/// simulation. Instead, most operations on the PORE (including setting up the
+/// initial state) are performed directly on the Pore model data member \a
+/// iv_pore itself. Similarly, memories are configured by map() operations
+/// directly on the memory objects.
+///
+/// The system components are created and interconnected in a simple two-step
+/// process:
+///
+/// - When objects are created any truly static configuration parameters are
+/// passed as arguments of the constructor.
+///
+/// - After all components are constructed, simple code sequences stitch
+/// together the components using a configure() method provided by each class
+/// of component.
+///
+/// This two-step sequence eliminates the problem of loops that would arise if
+/// we tried to configure the network in the constructor, and is very similar
+/// to the way that Simics models are configured.
+///
+/// The final PoreVe model is constructed in two steps. We first define a
+/// PoreVeBase model. This is a stripped down environment that only contains
+/// a PORE engine and the exact components required for the HBI application of
+/// PORE-SBE. The Vsbe facade class is later provided as the interface to
+/// PoreVeBase.
+///
+/// The second step of the derivation is to add all of the remaining
+/// components to create the full PoreVe model for use in VBU and lab
+/// applications. The derivation is done this way to make the PoreVeBase as
+/// small as possible in terms of both code and data size. Ideally however
+/// the differences (in code and data size) will turn out to be small enough
+/// such that we can drop the separate models and simply always create the
+/// full PoreVe model, using the Vsbe facade as the high-level interface for
+/// HBI. Frankly, the system design would probably be more robust if we had
+/// only one model - we may go ahead and merge the models anyway.
+
+#include <stdint.h>
+#include <stdarg.h>
+
+#include "fapi.H"
+
+#include "fasti2c.H"
+#include "poremodel.H"
+#include "pore.H"
+
+#ifdef VBU_HACKS
+#include "pib2cfam.H"
+#include "bsscan.H"
+#include "sbevital.H"
+#endif // VBU_HACKS
+
+#ifndef POREVE_STATISTICS
+#define POREVE_STATISTICS 0
+#endif
+
+namespace vsbe {
+
+ class PoreVeBase;
+ class PoreVe;
+
+ /// \defgroup poreve_config Parameters of PoreVe Configurations
+ ///
+ /// These parameters are required for configuring the PoreVe system model.
+ ///
+ /// \bug Many of these parameters are fake for now and will be system
+ /// dependent.
+ ///
+ /// @{
+
+ //////////////////////////////////////////////////////////////////////
+ // PORE
+ //////////////////////////////////////////////////////////////////////
+
+ /// The PIB base address of PORE-SBE control registers
+ const uint32_t PORE_SBE_PIB_BASE = 0x000e0000;
+
+ /// The PIB base address of PORE-SLW control registers
+ const uint32_t PORE_SLW_PIB_BASE = 0x00068000;
+
+ /// The size of the PORE control register space.
+ const uint64_t PORE_PIB_SIZE = ((uint64_t)SIZEOF_VISIBLE_PORE_STATE) / 8;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // OTPROM
+ //////////////////////////////////////////////////////////////////////
+
+ /// The PIB base address of the OTPROM memory controller
+ const uint32_t OTPROM_PIB_BASE = 0x00010000;
+
+ /// The number of PIB \e registers defined by the OTPROM memory controller
+ ///
+ /// PIB memories are 8-byte \e word addressed. The maximum amount of
+ /// memory accessible through the controller is (OTPROM_PIB_SIZE * 8)
+ /// bytes.
+ const uint64_t OTPROM_PIB_SIZE = 0x200;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // PIBMEM
+ //////////////////////////////////////////////////////////////////////
+
+ /// The PIB base address of the PIBMEM memory controller
+ const uint32_t PIBMEM_PIB_BASE = 0x00080000;
+
+ /// The number of PIB \e registers defined by the PIBMEM memory controller
+ ///
+ /// PIB memories are 8-byte \e word addressed. The maximum amount of
+ /// memory accessible through the controller is (PIBMEM_PIB_SIZE * 8)
+ /// bytes (3KB).
+ const uint64_t PIBMEM_PIB_SIZE = 0x180;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // PNOR
+ //////////////////////////////////////////////////////////////////////
+
+ /// The PIB base address of the PNOR (LPCM) memory controller
+ const uint32_t PNOR_PIB_BASE = 0x000b0000;
+
+ /// The number of registers defined by the PNOR memory controller
+ const size_t PNOR_PIB_SIZE = LPCM_REGISTERS;
+
+ /// The number of bytes in a PNOR address (actually a parameter of the
+ /// memory attached to the controller)
+ const size_t PNOR_ADDRESS_BYTES = 4;
+
+ /// The PNOR I2C Port Number
+ const unsigned PNOR_I2C_PORT = 0;
+
+ /// The PNOR I2C Device Address
+ const unsigned PNOR_I2C_DEVICE_ADDRESS = 0;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // SEEPROM
+ //////////////////////////////////////////////////////////////////////
+
+ /// The PIB base address of the SEEPROM memory controller
+ const uint32_t SEEPROM_PIB_BASE = 0x000c0000;
+
+ /// The number of registers defined by the SEEPROM memory controller
+ const uint64_t SEEPROM_PIB_SIZE = FASTI2C_REGISTERS;
+
+ /// The number of bytes in an SEEPROM address
+ const uint64_t SEEPROM_ADDRESS_BYTES = 2;
+
+ /// The SEEPROM I2C Port Number
+ const unsigned SEEPROM_I2C_PORT = 0;
+
+ /// The SEEPROM I2C Device Address
+ ///
+ /// \bug This value (0) is bogus, need the real value from the system
+ /// design.
+ const unsigned SEEPROM_I2C_DEVICE_ADDRESS = 0;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // PIB Default Catch-All Model
+ //////////////////////////////////////////////////////////////////////
+
+ /// The PIB base address of the default PIB slave
+ const uint32_t PIB_DEFAULT_PIB_BASE = 0x0;
+
+ /// The number of registers defined by the default PIB slave
+ const uint64_t PIB_DEFAULT_PIB_SIZE = 0x100000000ull;
+
+
+ //////////////////////////////////////////////////////////////////////
+ // OCI-Attached Components
+ //////////////////////////////////////////////////////////////////////
+
+ /// The OCI base address of the OCI PBA->Mainstore bridge
+ ///
+ /// We go ahead and map the entire 1GB. During configuration the actual
+ /// memory area in use will be defined by Memory::map() calls.
+ const uint32_t MAINSTORE_OCI_BASE = 0x00000000;
+
+ /// The OCI PBA->Mainstore bridge maps 1GB of the address space
+ const uint64_t MAINSTORE_OCI_SIZE = 0x40000000;
+
+
+ /// The OCI base address of the SRAM
+ const uint32_t SRAM_OCI_BASE = 0xfff80000;
+
+ /// The OCI SRAM is 512KB
+ const uint64_t SRAM_OCI_SIZE = 0x00080000;
+
+ /// The OCI address of the PMC_PORE_REQ_STAT_REG Register
+ ///
+ /// This is the only OCI control register that PORE-SLW should access, so
+ /// its size is limited to 8 bytes.
+ const uint32_t PMC_OCI_BASE = 0x40010480;
+
+ /// PORE-SLW is only allowed to access a specific 8 bytes of the OCI
+ /// control register space.
+ const uint64_t PMC_OCI_SIZE = 8;
+
+ /// @}
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreVeBase
+////////////////////////////////////////////////////////////////////////////
+
+/// The base class (HBI-only components) of PoreVe.
+///
+/// This model contains only those components required for HBI applications
+/// of the PORE virtual environment. Currently this is only
+///
+/// - A Pore
+/// - A PIB bus
+/// - A PNOR memory model
+/// - A PibSlave to catch any getscom()/putscom() destined for the PIB
+
+class
+vsbe::PoreVeBase {
+
+public:
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ /// Construct the PoreVeBase
+ ///
+ /// \param[in] i_id The PORE IBUF_ID (engine type) of the Pore component.
+ /// This will be PORE_SBE for host boot/SBE applications, and PORE_SLW for
+ /// testing Sleep/Winkle applications.
+ ///
+ /// \param[in] i_masterTarget The fapi::Target associated with the master
+ /// chip in an HBI master/slave configuration. This target is also
+ /// installed into \a iv_slaveTarget by the constructor.
+ PoreVeBase(const PoreIbufId i_id, const fapi::Target i_masterTarget);
+
+ virtual ~PoreVeBase();
+
+
+ //////////////////// Simulation Interface /////////////////////////
+
+ /// Reset the simulation to target a new slave
+ ///
+ /// \param[in] i_slaveTarget The slave target of the new slave
+ ///
+ /// The reset() method is provided to cleanly reset the simulation for
+ /// simulation with a new slave target. Once reset, the application is
+ /// responsible for setting up the register state of the Pore and invoking
+ /// the run() method to begin simulation.
+ virtual void
+ reset(fapi::Target i_slaveTarget);
+
+
+ /// See PoreModel::run()
+ ///
+ /// This API is provided as a convenience. Currently the only model in
+ /// the system that is 'clocked' is the PoreModel.
+ virtual int
+ run(const uint64_t i_instructions, uint64_t& o_ran);
+
+
+ /// Run a 'getscom' on the virtual PIB
+ ///
+ /// \param[in] i_address A 32-bit SCOM address
+ ///
+ /// \param[out] o_data The 64-bit SCOM data returned from the read
+ ///
+ /// \param[out] o_rc The 3-bit PIB/PCB error code returned from the PIB
+ /// transaction, see the PcbReturnCode enum in transaction.H.
+ ///
+ /// This method allows a caller to run a read transaction on the virtual
+ /// PIB bus, observing the same PIB configuration seen by the virtual PORE
+ /// engine. Accesses of PIB/PCB addresses that are modeled in the virtual
+ /// model return modeled results, and accesses of non-modeled addresses
+ /// are converted into FAPI calls.
+ ///
+ /// \returns A return value of 0 indicates success of the method call, but
+ /// does not guarantee that the PIB transaction succeeded. It will also be
+ /// necessary to also observe that PIB/PCB return code \a o_rc was
+ /// returned as 0. A non-0 return code from the method indicates a
+ /// modeling error.
+ virtual ModelError
+ getscom(const uint32_t i_address, uint64_t& o_data, int& o_rc);
+
+
+ /// Run a 'putscom' on the virtual PIB
+ ///
+ /// \param[in] i_address A 32-bit SCOM address
+ ///
+ /// \param[out] i_data The 64-bit SCOM write data
+ ///
+ /// \param[out] o_rc The 3-bit PIB/PCB error code returned from the PIB
+ /// transaction, see the PcbReturnCode enum in transaction.H.
+ ///
+ /// This method allows a caller to run a write transaction on the virtual
+ /// PIB bus, observing the same PIB configuration seen by the virtual PORE
+ /// engine. Accesses of PIB/PCB addresses that are modeled in the virtual
+ /// model update modeled registers, and accesses of non-modeled addresses
+ /// are converted into FAPI calls.
+ ///
+ /// \returns A return value of 0 indicates success of the method call, but
+ /// does not guarantee that the PIB transaction succeeded. It will also be
+ /// necessary to also observe that PIB/PCB return code \a o_rc was
+ /// returned as 0. A non-0 return code from the method indicates a
+ /// modeling error.
+ virtual ModelError
+ putscom(const uint32_t i_address, const uint64_t i_data, int& o_rc);
+
+
+ //////////////////// Public Implementation ////////////////////////////
+
+ /// The Pore model
+ Pore iv_pore;
+
+ /// The PIB bus model
+ Bus iv_pib;
+
+ /// The PNOR controller model
+ FastI2cController iv_pnorController;
+
+ /// The PNOR memory model
+ I2cMemory iv_pnorMemory;
+
+ /// The secondary PIB slave.
+ ///
+ /// This slave routes all operations that do not hit in a PIB-attached
+ /// memory model to hardware via FAPI getscom/putcom.
+ PibSlave iv_pibDefault;
+
+
+ //////////////////// Protected Implementation ///////////////////////////
+
+protected:
+
+ /// The PORE IBUF ID of the PORE engine
+ PoreIbufId iv_id;
+
+ /// The master fapi::Target
+ ///
+ /// HBI applications differentiate between the \e master chip that is
+ /// brought up first, and the \e slave chips that the master then
+ /// initializes. The master target is considered a constant and is
+ /// provided in the constructor. The master target is always associated
+ /// with the PNOR; the other memory components are associated with the
+ /// slave target. A pointer to this data member is provided to the PNOR
+ /// model during configuration.
+ fapi::Target iv_masterTarget;
+
+
+ /// The slave fapi::Target
+ ///
+ /// HBI applications differentiate between the \e master chip that is
+ /// brought up first, and the \e slave chips that the master then
+ /// initializes. The slave target is considered a variable and the
+ /// reset() method is provided to safely reset the system and modify the
+ /// slave target after construction. Note that the slave target is
+ /// initialized to be identical to the master target by the constructor.
+ /// A pointer to this data member is provided to all slaves other that the
+ /// PNOR model during configuration.
+ fapi::Target iv_slaveTarget;
+
+
+ /// The common ecmdDataBufferBase for all FAPI APIs
+ ///
+ /// To save memory space we only allocate one FAPI data buffer that is
+ /// used by all FAPI APIs that require a ecmdDataBuffer. A pointer to
+ /// this data member is provided to all slaves during configuration.
+ ecmdDataBufferBase iv_dataBuffer;
+
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ PoreVeBase(const PoreVeBase& i_rhs);
+ PoreVeBase& operator=(const PoreVeBase& i_rhs);
+};
+
+
+////////////////////////////////////////////////////////////////////////////
+// PoreVe
+////////////////////////////////////////////////////////////////////////////
+
+
+/// The full PoreVe configuration
+///
+/// This derivation from PoreVeBase adds the remaining PIB models not required
+/// by the HBI application, as well as all of the OCI models. Note that
+/// unlike the PIB there is no catch-all for OCI accesses; An access must hit
+/// within one of the defined memory maps, otherwise the access is considered
+/// an error.
+
+class
+vsbe::PoreVe : public vsbe::PoreVeBase {
+
+public:
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ /// Construct the PoreVe
+ ///
+ /// \param[in] i_id The PORE IBUF_ID (engine type) of the Pore component.
+ /// This will be PORE_SBE for host boot/SBE applications, and PORE_SLW for
+ /// testing Sleep/Winkle applications.
+ ///
+ /// \param[in] i_masterTarget The fapi::Target associated with the master
+ /// chip in an HBI master/slave configuration. This target is also
+ /// installed into \a iv_slaveTarget by the constructor.
+ PoreVe(const PoreIbufId i_id, const fapi::Target i_masterTarget);
+
+ virtual ~PoreVe();
+
+ /// Create a PoreVe (subclass) by static link-time selection
+ ///
+ /// \param[in] i_id The PORE IBUF_ID (engine type) of the Pore component.
+ /// This will be PORE_SBE for host boot/SBE applications, and PORE_SLW for
+ /// testing Sleep/Winkle applications.
+ ///
+ /// \param[in] i_masterTarget The fapi::Target associated with the master
+ /// chip in an HBI master/slave configuration. This target is also
+ /// installed into \a iv_slaveTarget by the constructor.
+ ///
+ /// \param[in] i_arg A private argument for the created model. In the
+ /// case of a debugged model this is a character string naming a script to
+ /// be run when the debugger starts. The PoreVe ignores this argument.
+ ///
+ /// The static create() method is provided to enable link-time selection
+ /// of a subclass of PoreVe, in particular to allow a common FAPI PoreVe
+ /// procedure to create either a 'normal' or 'debug' version of PoreVe.
+ static PoreVe* create(const PoreIbufId i_id,
+ const fapi::Target i_masterTarget,
+ const void* i_arg);
+
+ //////////////////// Public Implementation ////////////////////////////
+
+ /// The OTPROM controller model
+ PibMemory iv_otprom;
+
+ /// The OTPROM memory model
+ Memory iv_otpromMemory;
+
+ /// The PIBMEM controller model - No advanced functions implemented for now
+ PibMemory iv_pibmem;
+
+ /// The PIPMEM memory model
+ Memory iv_pibmemMemory;
+
+ /// The SEEPROM controller model
+ FastI2cController iv_seepromController;
+
+ /// The SEEPROM memory model
+ I2cMemory iv_seepromMemory;
+
+ /// The OCI bus model
+ Bus iv_oci;
+
+ /// The Mainstore memory controller model
+ OciMemory iv_main;
+
+ /// The Mainstore memory model
+ Memory iv_mainMemory;
+
+ /// The SRAM controller model
+ OciMemory iv_sram;
+
+ /// The SRAM memory model
+ Memory iv_sramMemory;
+
+#ifdef PM_HACKS
+ OciSlaveWritable iv_pmc;
+#endif // PM_HACKS
+
+#ifdef VBU_HACKS
+ /// The temporary Pib2Cfam PIB Slave
+ Pib2Cfam iv_pib2Cfam;
+
+ /// The temporary sbeVital PIB Slave
+ SbeVital iv_sbeVital;
+
+ /// The Broadside Scan components for each EX
+ // Bsscan iv_bsscan_ex00;
+ Bsscan iv_bsscan_ex01;
+ Bsscan iv_bsscan_ex02;
+ Bsscan iv_bsscan_ex03;
+ Bsscan iv_bsscan_ex04;
+ Bsscan iv_bsscan_ex05;
+ Bsscan iv_bsscan_ex06;
+ // Bsscan iv_bsscan_ex07;
+ // Bsscan iv_bsscan_ex08;
+ Bsscan iv_bsscan_ex09;
+ Bsscan iv_bsscan_ex10;
+ Bsscan iv_bsscan_ex11;
+ Bsscan iv_bsscan_ex12;
+ Bsscan iv_bsscan_ex13;
+ Bsscan iv_bsscan_ex14;
+ // Bsscan iv_bsscan_ex15;
+#endif
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ PoreVe(const PoreVe& i_rhs);
+ PoreVe& operator=(const PoreVe& i_rhs);
+};
+
+#endif // __VSBE_POREVE_H
diff --git a/src/usr/pore/poreve/porevesrc/sbevital.C b/src/usr/pore/poreve/porevesrc/sbevital.C
new file mode 100644
index 000000000..1a80337db
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/sbevital.C
@@ -0,0 +1,82 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/sbevital.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+// -*- mode: C++; c-file-style: "linux"; -*-
+// $Id: sbevital.C,v 1.1 2011/09/19 00:25:32 jeshua Exp $
+
+/// \file sbevital.C
+/// \brief A temporary hack to create the SBE vital reg before HW has it
+///
+#ifdef VBU_HACKS
+
+#include "sbevital.H"
+#include "fapiSharedUtils.H"
+#include "ecmdUtils.H"
+using namespace vsbe;
+
+
+////////////////////////////// Creators //////////////////////////////
+
+SbeVital::SbeVital()
+{
+ iv_data = 0;
+}
+
+
+SbeVital::~SbeVital()
+{
+}
+
+
+//////////////////////////// Manipulators ////////////////////////////
+
+fapi::ReturnCode
+SbeVital::operation(Transaction& io_transaction)
+{
+ fapi::ReturnCode rc=0;
+ ModelError me;
+
+ FAPI_INF("In sbeVital\n");
+
+ //On a ring write, put the data into the ring
+ if( io_transaction.iv_mode == ACCESS_MODE_WRITE)
+ {
+ iv_data = io_transaction.iv_data >> 32;
+ me = ME_SUCCESS;
+ }
+ else if( io_transaction.iv_mode == ACCESS_MODE_READ )
+ {
+ io_transaction.iv_data = ((uint64_t)(iv_data)) << 32;
+ me = ME_SUCCESS;
+ }
+ else
+ {
+ me = ME_FAILURE;
+ }
+
+ io_transaction.busError(me);
+ return rc;
+}
+#endif
+/* Local Variables: */
+/* c-basic-offset: 4 */
+/* End: */
diff --git a/src/usr/pore/poreve/porevesrc/sbevital.H b/src/usr/pore/poreve/porevesrc/sbevital.H
new file mode 100644
index 000000000..66aa83f96
--- /dev/null
+++ b/src/usr/pore/poreve/porevesrc/sbevital.H
@@ -0,0 +1,85 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/porevesrc/sbevital.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2012
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __VSBE_SBEVITAL_H
+#define __VSBE_SBEVITAL_H
+
+// $Id: sbevital.H,v 1.1 2011/09/19 00:25:32 jeshua Exp $
+
+/// \file sbevital.H
+/// \brief A hack to intercept scan operations and make them broadside
+
+#include "bus.H"
+
+namespace vsbe {
+
+ class SbeVital;
+
+ /// PIB base address of PIB range mapped by SbeVital
+ const uint32_t SBEVITAL_PIB_BASE = 0x0005001C;
+
+ /// Number of PIB addresses mapped by SbeVital
+ const int SBEVITAL_PIB_SIZE = 1;
+
+}
+
+
+/// Map PIB accesses to CFAM accesses
+
+class
+vsbe::SbeVital : public PibSlave {
+
+public:
+
+ ////////////////////////////// Creators //////////////////////////////
+
+ SbeVital();
+
+ virtual ~SbeVital();
+
+
+ //////////////////////////// Manipulators ////////////////////////////
+
+ /// SbeVital operation
+ ///
+ /// \param[in,out] io_transaction A PIB transaction object
+ ///
+ /// This object converts PIB transactions in a certain range in the
+ /// virtual environment to broadside getRing and putRing operations,
+ /// returning the FAPI return code from the translated calls.
+ ///
+ /// \retval rc The fapi::ReturnCode returned by the underlying
+ /// getRing() or putRing() call.
+ fapi::ReturnCode
+ operation(Transaction& io_transaction);
+
+
+ ///////////////////////////// Safety //////////////////////////////////
+
+private:
+ SbeVital(const SbeVital& rhs);
+ SbeVital& operator=(const SbeVital& rhs);
+
+ uint32_t iv_data;
+};
+
+#endif // __VSBE_SBEVITAL_H
diff --git a/src/usr/pore/poreve/poreveutil.C b/src/usr/pore/poreve/poreveutil.C
new file mode 100644
index 000000000..3d8059061
--- /dev/null
+++ b/src/usr/pore/poreve/poreveutil.C
@@ -0,0 +1,35 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/poreve/poreveutil.C $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2011
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#include <trace/interface.H>
+
+//******************************************************************************
+// Trace descriptors
+//******************************************************************************
+trace_desc_t* g_poreDbgTd = NULL;
+trace_desc_t* g_poreErrTd = NULL;
+
+//******************************************************************************
+// Global TracInit objects. Construction will initialize the trace buffer
+//******************************************************************************
+TRAC_INIT(&g_poreDbgTd, "PORE_D", 4096);
+TRAC_INIT(&g_poreErrTd, "PORE_E", 4096);
diff --git a/src/usr/pore/test/makefile b/src/usr/pore/test/makefile
new file mode 100644
index 000000000..884fe5ec5
--- /dev/null
+++ b/src/usr/pore/test/makefile
@@ -0,0 +1,37 @@
+# IBM_PROLOG_BEGIN_TAG
+# This is an automatically generated prolog.
+#
+# $Source: src/usr/pore/test/makefile $
+#
+# IBM CONFIDENTIAL
+#
+# COPYRIGHT International Business Machines Corp. 2011
+#
+# p1
+#
+# Object Code Only (OCO) source materials
+# Licensed Internal Code Source Materials
+# IBM HostBoot Licensed Internal Code
+#
+# The source code for this program is not published or other-
+# wise divested of its trade secrets, irrespective of what has
+# been deposited with the U.S. Copyright Office.
+#
+# Origin: 30
+#
+# IBM_PROLOG_END
+ROOTPATH = ../../../..
+
+MODULE = testpore
+
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/ecmddatabuffer
+EXTRAINCDIR += ${ROOTPATH}/src/usr/pore/fapiporeve
+EXTRAINCDIR += ${ROOTPATH}/src/usr/pore/poreve/model
+EXTRAINCDIR += ${ROOTPATH}/src/usr/pore/poreve/porevesrc
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/fapi
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/plat
+EXTRAINCDIR += ${ROOTPATH}/src/include/usr/hwpf/hwp
+
+TESTS = *.H
+
+include ${ROOTPATH}/config.mk
diff --git a/src/usr/pore/test/poretest.H b/src/usr/pore/test/poretest.H
new file mode 100644
index 000000000..bc3cd5e72
--- /dev/null
+++ b/src/usr/pore/test/poretest.H
@@ -0,0 +1,181 @@
+// IBM_PROLOG_BEGIN_TAG
+// This is an automatically generated prolog.
+//
+// $Source: src/usr/pore/test/poretest.H $
+//
+// IBM CONFIDENTIAL
+//
+// COPYRIGHT International Business Machines Corp. 2011
+//
+// p1
+//
+// Object Code Only (OCO) source materials
+// Licensed Internal Code Source Materials
+// IBM HostBoot Licensed Internal Code
+//
+// The source code for this program is not published or other-
+// wise divested of its trade secrets, irrespective of what has
+// been deposited with the U.S. Copyright Office.
+//
+// Origin: 30
+//
+// IBM_PROLOG_END
+#ifndef __PORETEST_H
+#define __PORETEST_H
+
+/**
+ * @file poretest.H
+ *
+ * @brief Test case for POREVE code
+*/
+
+#include <list>
+#include <cxxtest/TestSuite.H>
+#include <targeting/targetservice.H>
+#include <fapiPoreVeArg.H>
+#include <fapiTarget.H>
+#include <fapi.H>
+#include <vfs/vfs.H>
+
+using namespace TARGETING;
+using namespace vsbe;
+extern fapi::ReturnCode fapiPoreVe(const fapi::Target i_target,
+ std::list<uint64_t> & io_sharedObjectArgs);
+
+class PoreTest: public CxxTest::TestSuite
+{
+public:
+ /**
+ * @brief PORE test #1
+ * Run a sample procedure
+ */
+ void testPore1(void)
+ {
+ fapi::ReturnCode l_rc = fapi::FAPI_RC_SUCCESS;
+ fapi::ReturnCode l_rc2 = fapi::FAPI_RC_SUCCESS;
+ bool l_unloadSbePnorImg = false;
+ size_t l_sbePnorSize = 0;
+ const char * l_sbePnorAddr = NULL;
+
+ errlHndl_t l_errl = NULL;
+
+ do
+ {
+ // Loading sbe_pnor img
+ l_errl = VFS::module_load("sbe_pnor.bin");
+ if (l_errl)
+ {
+ TS_FAIL("testPore1: Error loading sbe_pnor.bin!");
+ break;
+ }
+ else
+ {
+ // Set flag to unload
+ l_unloadSbePnorImg = true;
+ l_errl = VFS::module_address("sbe_pnor.bin", l_sbePnorAddr, l_sbePnorSize);
+ if(l_errl)
+ {
+ TS_FAIL("testPore1: Error getting load address of sbe_pnor.bin!");
+ break;
+ }
+ else
+ {
+ char l_header[10];
+ memcpy (l_header, l_sbePnorAddr, 9);
+ l_header[9] = '\0';
+ FAPI_INF("Loading sbe_pnor.bin, Addr 0x%llX, Size %d, Header %s",
+ l_sbePnorAddr, l_sbePnorSize, l_header);
+ }
+ }
+
+ // Setting up fapi target
+ TARGETING::TargetService& l_targetService =
+ TARGETING::targetService();
+ TARGETING::Target* l_testTarget = NULL;
+ l_targetService.masterProcChipTargetHandle(l_testTarget);
+ assert(l_testTarget != NULL);
+
+ // Setup args
+ std::list<uint64_t> myArgs;
+
+ // Run unlimited instruction on SBE engine
+ FapiPoreVeOtherArg *l_otherArg =
+ new FapiPoreVeOtherArg(vsbe::RUN_UNLIMITED,
+ vsbe::PORE_SBE);
+ //Set entry point
+ //l_otherArg->iv_entryPoint = const_cast<char*>("pnor::_sbe_pnor_start");
+ //l_otherArg->iv_entryPoint = const_cast<char*>("pnor::proc_sbe_fabricinit");
+ l_otherArg->iv_entryPoint = const_cast<char*>("pnor::proc_sbe_pb_startclocks");
+
+ l_otherArg->iv_mrr = 0x280000000;
+
+ uint64_t fapiArg = reinterpret_cast<uint64_t> (l_otherArg);
+ myArgs.push_back(fapiArg);
+
+ // Set FapiPoreVeMemArg for pnor option, base address = 0
+ uint32_t base_addr = 0;
+ char* l_dataPnor = const_cast<char*>(l_sbePnorAddr);
+ //@todo - Need to somehow avoid manually entering file size here.
+ FapiPoreVeMemArg* l_memArg = new FapiPoreVeMemArg(ARG_PNOR,
+ base_addr, 31360, static_cast<void*>(l_dataPnor));
+ fapiArg = reinterpret_cast<uint64_t> (l_memArg);
+ myArgs.push_back(fapiArg);
+
+ // Create state argument to dump out state for debugging purpose
+ FapiPoreVeStateArg *l_stateArg = new FapiPoreVeStateArg(NULL);
+ l_stateArg->iv_installState = false;
+ l_stateArg->iv_extractState = true;
+ fapiArg = reinterpret_cast<uint64_t> (l_stateArg);
+ myArgs.push_back(fapiArg);
+
+ // Create a FAPI Target
+ fapi::Target l_fapiTarget(fapi::TARGET_TYPE_PROC_CHIP,
+ reinterpret_cast<void *> (l_testTarget));
+
+ //@todo - Comment out the actual run for now because
+ // the "halt" instruction causes poreve to scom SBEVITAL cfam reg,
+ // which causes an error in SIMICs.
+ // VBU model also has a hack that models this register
+ //l_rc = fapiPoreVe(l_fapiTarget, myArgs);
+ if (l_rc != fapi::FAPI_RC_SUCCESS)
+ {
+ uint32_t val = l_rc;
+ FAPI_ERR("testPore1: Error from fapiPoreVe 0x%llX", val);
+ }
+ else
+ {
+ FAPI_INF("testPore1: fapiPoreVe runs successfully!");
+ }
+
+ } while(0);
+
+ // Unload sbe_pnor
+ if (l_unloadSbePnorImg == true)
+ {
+ l_rc2 = fapiUnloadInitFile("sbe_pnor.bin", l_sbePnorAddr,
+ l_sbePnorSize);
+ if (l_rc2 != fapi::FAPI_RC_SUCCESS)
+ {
+ FAPI_ERR("testPore1: Error unloading sbe_pnor.bin");
+ if (l_rc == fapi::FAPI_RC_SUCCESS)
+ {
+ l_rc = l_rc2;
+ }
+ }
+ }
+
+ // Test fail/pass
+ if (l_rc != fapi::FAPI_RC_SUCCESS)
+ {
+ TS_FAIL("testPore1 fails! Check FAPI trace");
+ }
+ else
+ {
+ TS_TRACE("testPore1 ran successfully!");
+ }
+
+ return;
+ }
+};
+
+#endif
OpenPOWER on IntegriCloud