diff options
Diffstat (limited to 'src/ssx')
117 files changed, 41841 insertions, 0 deletions
diff --git a/src/ssx/pgp/Makefile b/src/ssx/pgp/Makefile new file mode 100755 index 0000000..417a452 --- /dev/null +++ b/src/ssx/pgp/Makefile @@ -0,0 +1,38 @@ +# $Id: Makefile,v 1.2 2013/12/12 16:12:28 bcbrock Exp $ + +# This Makefile compiles all of the SSX code required for the PgP port +# of SSX. See the "ssx.mk" file in this directory. + +include ssx.mk +include ssxpgpfiles.mk + + +ifeq "$(SSX_TIMER_SUPPORT)" "1" +PGP_OBJECTS += ${PGP-TIMER-C-SOURCES:.c=.o} ${PGP-TIMER-S-SOURCES:.S=.o} +endif + +ifeq "$(SSX_THREAD_SUPPORT)" "1" +PGP_OBJECTS += ${PGP-THREAD-C-SOURCES:.c=.o} ${PGP-THREAD-S-SOURCES:.S=.o} +endif + +ifeq "$(PGP_ASYNC_SUPPORT)" "1" +PGP_OBJECTS += ${PGP-ASYNC-C-SOURCES:.c=.o} ${PGP-ASYNC-S-SOURCES:.S=.o} +endif + + +all: local + $(MAKE) -I ../pgp -C ../ssx + $(MAKE) -I ../pgp -C ../ppc405 + +local: $(PGP_OBJECTS) + + +.PHONY : clean +clean: + rm -f *.o *.d *.d.* *.ps *.pdf + $(MAKE) -I ../pgp -C ../ssx clean + $(MAKE) -I ../pgp -C ../ppc405 clean + +ifneq ($(MAKECMDGOALS),clean) +include $(PGP_OBJECTS:.o=.d) +endif diff --git a/src/ssx/pgp/linkssx.cmd b/src/ssx/pgp/linkssx.cmd new file mode 100755 index 0000000..0556a03 --- /dev/null +++ b/src/ssx/pgp/linkssx.cmd @@ -0,0 +1,499 @@ +// $Id: linkssx.cmd,v 1.2 2014/03/14 16:33:45 bcbrock Exp $ + +// This linker script creates SRAM images of SSX applications for PgP. This +// script is processed through the C proprocessor to create +// configuration-dependent images. +// +// All sections with different MMU protection properties are 1KB-aligned, even +// when linked in real-addressing mode. +// +// NB: According to *info* manual for ld, it should not be necessary to specify +// the '.' in the section commands, e.g., +// +// .data.startup . : { *(.data.startup) } > sram +// +// However without these the sections are not aligned properly, as the linker +// seems to ignore the LC and move the section 'backwards' until it abuts +// (aligned) with the previous one. +// +// Info on PPC binaries: +// http://devpit.org/wiki/Debugging_PowerPC_ELF_Binaries + +// Need to do this so that elf32-powerpc is not modified! +#undef powerpc + +#ifndef INITIAL_STACK_SIZE +#define INITIAL_STACK_SIZE 2000 +#endif + +OUTPUT_FORMAT(elf32-powerpc); + +// Define the beginning of SRAM, the location of the PowerPC exception +// vectors (must be 64K-aligned) and the location of the boot branch. + +// 512 KB SRAM at the top of the 32-bit address space + +#define origin 0xfff80000 +#define vectors 0xfff80000 +#define reset 0xffffffec +#define sram_available (reset - origin) +#define sram_size 0x00080000 + +// The SRAM controller aliases the SRAM at 8 x 128MB boundaries to support +// real-mode memory attributes using DCCR, ICCR etc. Noncacheable access is +// the next-to-last 128MB PPC405 region. Write-though access is the +// next-to-next-to-last 128MB PPC405 region + +#define noncacheable_offset 0x08000000 +#define noncacheable_origin (origin - 0x08000000) + +#define writethrough_offset 0x10000000 +#define writethrough_origin (origin - 0x10000000) + +// Define SSX kernel text sections to be packed into nooks and crannies of +// the exception vector area. An option is provided _not_ to pack, to help +// better judge the best way to pack. Note that any code eligible for packing +// is considered 'core' code that will be needed by the application at +// runtime. Any header data is _always_ packed into .vectors_0000 however. +// +// Note that in order to support MMU protection, we can't pack data along +// with the text. All of the packed data sections are thus left empty. + + +// .vectors_0000 + +#define text_0000 \ +*(.vectors_0000) + +#define data_0000 + + +// .vectors_0100 + +#define text_0100 \ +ppc405_core.o(.text) \ +ppc405_irq_core.o(.text) + +#define data_0100 + + +// .vectors_0c00 + +#if SSX_TIMER_SUPPORT +#define text_0c00_conditional +#else +#define text_0c00_conditional +#endif + + +#define text_0c00 \ +text_0c00_conditional \ +ppc405_cache_core.o(.text) + +#define data_0c00 + + +// .vectors_0f00 + +#if SSX_TIMER_SUPPORT + +#if SSX_THREAD_SUPPORT +#define text_0f00_conditional \ +ssx_timer_init.o(.text) \ +ssx_timer_core.o(.text) \ +ssx_semaphore_core.o(.text) +#endif /* SSX_THREAD_SUPPORT */ + +#if !SSX_THREAD_SUPPORT +#define text_0f00_conditional \ +ssx_timer_init.o(.text) \ +ssx_timer_core.o(.text) +#endif /* !SSX_THREAD_SUPPORT */ + +#else /* SSX_TIMER_SUPPORT */ + +#define text_0f00_conditional +#endif /* SSX_TIMER_SUPPORT */ + +#define text_0f00 \ +text_0f00_conditional + +#define data_0f00 + +// .vectors_2000 + +#if SSX_THREAD_SUPPORT +#define thread_text \ +ssx_thread_init.o(.text) \ +ssx_thread_core.o(.text) \ +ppc405_irq_init.o(.text) \ +ppc405_thread_init.o(.text) \ +ssx_semaphore_init.o(.text) +#else +#define thread_text +#endif + +#if PPC405_MMU_SUPPORT +#define mmu_text \ +ppc405_mmu.o(.text)\ +ppc405_mmu_asm.o(.text) +#else +#define mmu_text +#endif + +#define text_2000 \ +pgp_irq_init.o(.text) \ +ppc405_cache_init.o(.text) \ +ppc405_breakpoint.o(.text) \ +pgp_cache.o(.text) \ +ssx_stack_init.o(.text) \ +thread_text \ +mmu_text \ +pgp_async.o(.text) \ +pgp_async_pore.o(.text) \ +pgp_async_ocb.o(.text) \ +pgp_async_pba.o(.text) \ +pgp_pmc.o(.text) \ +pgp_ocb.o(.text) \ +pgp_pba.o(.text) \ +pgp_id.o(.text) \ +pgp_centaur.o(.text) \ +ppc405_lib_core.o(.text) \ +ssx_core.o(.text) \ + +#define data_2000 + +// .vectors_0000 is always packed with header information + +#define pack_0000 text_0000 data_0000 +#define nopack_0000 + +#ifndef NO_PACK_SSX + +#define pack_0100 text_0100 data_0100 +#define nopack_0100 + +#define pack_0c00 text_0c00 data_0c00 +#define nopack_0c00 + +#define pack_0f00 text_0f00 data_0f00 +#define nopack_0f00 + +#define pack_2000 text_2000 data_2000 +#define nopack_2000 + +#else + +#define pack_0100 +#define nopack_0100 text_0100 data_0100 + +#define pack_0c00 +#define nopack_0c00 text_0c00 data_0c00 + +#define pack_0f00 +#define nopack_0f00 text_0f00 data_0f00 + +#define pack_2000 +#define nopack_2000 text_2000 data_2000 + +#endif + +#define init_text \ +ssx_init.o(.text) \ +ppc405_boot.o(.text) \ +ppc405_init.o(.text) \ +pgp_init.o(.text) + +// Define memory areas. + +MEMORY +{ + sram : ORIGIN = origin, LENGTH = sram_available + noncacheable : ORIGIN = noncacheable_origin, LENGTH = sram_available + writethrough : ORIGIN = writethrough_origin, LENGTH = sram_available + boot : ORIGIN = reset, LENGTH = 20 +} + +// NB: The code that sets up the MMU assumes that the linker script provides a +// standard set of symbols that define the base address and size of each +// expected section. Any section with a non-0 size will be mapped in the MMU +// using protection attributes appropriate for the section. All sections +// requiring different MMU attributes must be 1KB-aligned. + +SECTIONS +{ + . = origin; + . = vectors; + + _MEMORY_ORIGIN = .; + _MEMORY_SIZE = sram_size; + + //////////////////////////////// + // Text0 + //////////////////////////////// + + // Low-memory kernel code and any other code that would benefit from being + // resident in lower-latency SRAM + + _TEXT0_SECTION_BASE = .; + _PPC405_VECTORS_BASE = .; + + .exceptions . : { + ___vectors = .; + ppc405_exceptions.o(.vectors_0000) + pack_0000 + . = ___vectors + 0x0100; + ppc405_exceptions.o(.vectors_0100) + pack_0100 + . = ___vectors + 0x0c00; + ppc405_exceptions.o(.vectors_0c00) + pack_0c00 + . = ___vectors + 0x0f00; + ppc405_exceptions.o(.vectors_0f00) + pack_0f00 + . = ___vectors + 0x2000; + ppc405_exceptions.o(.vectors_2000) + pack_2000 + } > sram + + // If we're not packing, then place 'core' code immediately after the + // exception vectors. + + .nopack . : { nopack_0000 nopack_0100 nopack_0c00 nopack_0f00 nopack_2000 } > sram + + . = ALIGN(1024); + _TEXT0_SECTION_SIZE = . - _TEXT0_SECTION_BASE; + + //////////////////////////////// + // Noncacheable and Write-through Data + //////////////////////////////// + + // Non-cacheable and write-through data is placed in low memory to + // improve latency. PORE-private text and data is also placed here. PORE + // text and data are segregated to enable relocated PORE disassembly of + //.text.pore. PORE text is read-only to OCC, however PORE data is writable + // by OCC to allow shared data structures (e.g., PTS). + + // When running without the MMU we need to carefully arrange things such + // that the noncacheable and writethrough data is linked at the correct + // aliased VMA while remaining loaded in contiguous LMA addresses. + +#if PPC405_MMU_SUPPORT + +#define ALIASED_SECTION(s) s . : {*(s)} > sram + +#else + +#define ALIASED_SECTION(s) \ + _LMA = . + _lma_offset; \ + s . : AT (_LMA) {*(s)} + +#endif + +#if !PPC405_MMU_SUPPORT + . = . - noncacheable_offset; + _lma_offset = noncacheable_offset; +#endif + + _NONCACHEABLE_RO_SECTION_BASE = .; + + ALIASED_SECTION(.noncacheable_ro) + ALIASED_SECTION(.text.pore) + + . = ALIGN(1024); + _NONCACHEABLE_RO_SECTION_SIZE = . - _NONCACHEABLE_RO_SECTION_BASE; + + + _NONCACHEABLE_SECTION_BASE = .; + + ALIASED_SECTION(.noncacheable) + ALIASED_SECTION(.data.pore) + + . = ALIGN(1024); + _NONCACHEABLE_SECTION_SIZE = . - _NONCACHEABLE_SECTION_BASE; + + +#if !PPC405_MMU_SUPPORT + . = . + noncacheable_offset - writethrough_offset; + _lma_offset = writethrough_offset; +#endif + + + _WRITETHROUGH_SECTION_BASE = .; + + ALIASED_SECTION(.writethrough) + + . = ALIGN(1024); + _WRITETHROUGH_SECTION_SIZE = . - _WRITETHROUGH_SECTION_BASE; + +#if !PPC405_MMU_SUPPORT + . = . + writethrough_offset; +#endif + + + //////////////////////////////// + // Read-only Data + //////////////////////////////// + + // Accesses of read-only data may or may not benefit from being in fast + // SRAM - we'll give it the benefit of the doubt. + + _RODATA_SECTION_BASE = .; + + // SDA2 constant sections .sdata2 and .sbss2 must be adjacent to each + // other. Our SDATA sections are small so we'll use strictly positive + // offsets. + + _SDA2_BASE_ = .; + .sdata2 . : { *(.sdata2) } > sram + .sbss2 . : { *(.sbss2) } > sram + + // The .rodata.vclcommand section contains read-only VclCommandRecord for + // the benefit of the vcl_console() command interpreter. + + _VCL_COMMAND_SECTION_BASE = .; + .rodata.vclcommand . : { *(.rodata.vclcommand) } > sram + _VCL_COMMAND_SECTION_SIZE = . - _VCL_COMMAND_SECTION_BASE; + + // The .rodata.vclthread section contains read-only VclThreadRecord for the + // benefit of the thread command. + + _VCL_THREAD_SECTION_BASE = .; + .rodata.vclthread . : { *(.rodata.vclthread) } > sram + _VCL_THREAD_SECTION_SIZE = . - _VCL_THREAD_SECTION_BASE; + + // The .rodata.vclpackage section contains read-only char* pointers for the + // benefit of the package command. + + _VCL_PACKAGE_SECTION_BASE = .; + .rodata.vclpackage . : { *(.rodata.vclpackage) } > sram + _VCL_PACKAGE_SECTION_SIZE = . - _VCL_PACKAGE_SECTION_BASE; + + // Other read-only data. + + .rodata . : { *(.rodata*) *(.got2) } > sram + + . = ALIGN(1024); + _RODATA_SECTION_SIZE = . - _RODATA_SECTION_BASE; + + //////////////////////////////// + // Text1 + //////////////////////////////// + + // The default text section + + _TEXT1_SECTION_BASE = .; + + // Initialization text. If we ever do a scheme to get rid of + // initialization text then this will have to be moved if we're also doing + // MMU protection. + + .itext . : { init_text } > sram + + // Other text + // It's not clear why boot.S is generating empty .glink,.iplt + + .otext . : { *(.text) *(.text.startup)} > sram + .glink . : { *(.glink) } > sram + + . = ALIGN(1024); + _TEXT1_SECTION_SIZE = . - _TEXT1_SECTION_BASE; + + //////////////////////////////// + // Read-write Data + //////////////////////////////// + + _DATA_SECTION_BASE = .; + + // SDA sections .sdata and .sbss must be adjacent to each + // other. Our SDATA sections are small so we'll use strictly positive + // offsets. + + _SDA_BASE_ = .; + .sdata . : { *(.sdata) } > sram + .sbss . : { *(.sbss) } > sram + + // Other read-write data + // It's not clear why boot.S is generating empty .glink,.iplt + + .rela . : { *(.rela*) } > sram + .rwdata . : { *(.data) *(.bss) } > sram + .iplt . : { *(.iplt) } > sram + + + // Initialization-only data. This includes the stack of main, the data + // structures declared by INITCALL, and any other data areas that can be + // reclaimed to the heap after initialization. + // + // NB: If we ever do reclaim this space, we need to modify the concept of + // executable free space. + + _INIT_ONLY_DATA_BASE = .; + + _SSX_INITIAL_STACK_LIMIT = .; + . = . + INITIAL_STACK_SIZE; + _SSX_INITIAL_STACK = . - 1; + + _INITCALL_SECTION_BASE = .; + .data.initcall . : { *(.data.initcall) } > sram + _INITCALL_SECTION_SIZE = . - _INITCALL_SECTION_BASE; + + .data.startup . : { *(.data.startup) } > sram + + _INIT_ONLY_DATA_SIZE = . - _INIT_ONLY_DATA_BASE; + + //////////////////////////////// + // Free Space + //////////////////////////////// + + // If the configuration allows executing from free space - i.e., + // malloc()-ing a buffer and loading and executing code from it - then the + // free space is separated and aligned so that it can be marked executable. + // Otherwise it is simply read/write like the normal data sections. + +#ifndef EXECUTABLE_FREE_SPACE +#define EXECUTABLE_FREE_SPACE 0 +#endif + +#if PPC405_MMU_SUPPORT && EXECUTABLE_FREE_SPACE + . = ALIGN(1024); +#endif + + // The free space available to the program starts here. This space does + // not include the initial stack used by the boot loader and main(). The + // initial stack space is considered part of the free 'section' for MMU + // purposes. Free space is always 8-byte aligned. + // + // Note that there is no data after _SSX_FREE_START. When binary images + // are created they can be padded to _SSX_FREE_START to guarantee + // that .bss and COMMON data are zeroed, and that the images contain an + // even multiple of 8 bytes (required for HW loaders). + + . = ALIGN(8); + _EX_FREE_SECTION_BASE = .; + _SSX_FREE_START = .; + +#if EXECUTABLE_FREE_SPACE + _DATA_SECTION_SIZE = . - _DATA_SECTION_BASE; + _EX_FREE_SECTION_SIZE = 0 - _EX_FREE_SECTION_BASE; +#else + _DATA_SECTION_SIZE = 0 - _DATA_SECTION_BASE; + _EX_FREE_SECTION_SIZE = 0; +#endif + + //////////////////////////////// + // Applet areas + //////////////////////////////// + + // These symbols are currently unused, but required to be defined. + + _APPLET0_SECTION_BASE = 0; + _APPLET0_SECTION_SIZE = 0; + _APPLET1_SECTION_BASE = 0; + _APPLET1_SECTION_SIZE = 0; + + // The final 16 bytes of memory are reserved for the hardware boot branch + + _SSX_FREE_END = reset - 1; +} + diff --git a/src/ssx/pgp/pgp.h b/src/ssx/pgp/pgp.h new file mode 100755 index 0000000..fb99e4f --- /dev/null +++ b/src/ssx/pgp/pgp.h @@ -0,0 +1,328 @@ +#ifndef __PGP_H__ +#define __PGP_H__ + +// $Id: pgp.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp.h +/// \brief The PgP environment for SSX. + +// This is a 'circular' reference in SSX, but included here to simplify PGAS +// programming. + +#ifndef CHIP_PGP +#define CHIP_PGP +#include "ppc405.h" +#endif + +// Can't include this here due to ordering issues. It's included in +// ppc405_irq.h. +// #include "pgp_irq.h" + +// Required for MMU Map declarations +#include "ppc405_mmu.h" + +#include "pgp_common.h" +#include "pgp_core.h" +#include "pgp_trace.h" +#include "pgp_ocb.h" +#include "pgp_pba.h" +#include "pgp_pore.h" +#include "pgp_pmc.h" +#include "pgp_sramctl.h" +#include "pgp_vrm.h" +#include "pgp_id.h" +#include "pgp_centaur.h" + +#include "pcbs_register_addresses.h" +#include "pcbs_firmware_registers.h" + +#include "tod_register_addresses.h" +#include "tod_firmware_registers.h" + +#include "plb_arbiter_register_addresses.h" +#include "plb_arbiter_firmware_registers.h" + +#include "mcs_register_addresses.h" +#include "mcs_firmware_registers.h" + +#include "centaur_firmware_registers.h" +#include "centaur_register_addresses.h" + +#include "tpc_register_addresses.h" +#include "tpc_firmware_registers.h" + +#include "oha_register_addresses.h" +#include "oha_firmware_registers.h" + + +// Include other driver headers + +#include "pgp_async.h" + +/// \defgroup memory_map Real-mode memory map setup for SRAM-resident applications +/// +/// Below are the interpretations of the default settings of the real-mode +/// memory control registers. All of the settings can be overridden as +/// compile switches for special test purposes. +/// +/// The final 128MB of memory (the SRAM) is mapped both I- and +/// D-cacheable. The other 7 high-memory regions aliased by the SRAM remain +/// uncacheable, however SRAM alias region 29 is marked write-through. +/// +/// Low memory addresses (direct-map Mainstore via PBA) are I-cacheable +/// but not D-cacheable to improve predicatability of execution times. +/// However, we should not execute from mainstore after initialization. +/// +/// OCI register space (Segment '0b01') is marked guarded and non-cacheable. +/// +/// All memory is big-endian. +/// +/// @{ + +#ifndef PPC405_ICCR_INITIAL +#define PPC405_ICCR_INITIAL 0xff000001 +#endif + +#ifndef PPC405_DCCR_INITIAL +#define PPC405_DCCR_INITIAL 0x00000001 +#endif + +#ifndef PPC405_DCWR_INITIAL +#define PPC405_DCWR_INITIAL 0x00000004 +#endif + +#ifndef PPC405_SGR_INITIAL +#define PPC405_SGR_INITIAL 0x00ff0000 +#endif + +#ifndef PPC405_SU0R_INITIAL +#define PPC405_SU0R_INITIAL 0x00000000 +#endif + +#ifndef PPC405_SLER_INITIAL +#define PPC405_SLER_INITIAL 0x00000000 +#endif + +/// @} + + +/// PgP always runs from a memory image + +#define SSX_RUN_FROM_MEMORY 1 + +/// This is the initial value of Cache Control Register 0 (CCR0) for PgP. +/// This definition can be overridden by the application. +/// +/// The default setting: +/// +/// - Enables parity checking in the caches and TLBs. The parity mode is not +/// modified and defaults to 'imprecise'. +/// +/// - Enables ICU prefetching for cacheable regions (Subject to final +/// performance evaluation). Non-cacheable regions are not prefetched. +/// +/// - Gives highest PLB priority to ICU fetches. This setting can be +/// overriden by scan-only dials in the PgP design which force a fixed +/// priority on the ICU. +/// +/// - Sets priority bit 1 to '1' for DCU operations. The DCU sets priority +/// bit 0 automatically. This setting can also be overridden by scan-only +/// dials that force a fixed priority on the DCU +/// +/// Other options can be set at run time with the API \c ppc405_ccr0_modify(). + +#ifndef PPC405_CCR0_INITIAL +#define PPC405_CCR0_INITIAL \ + (CCR0_DPE | CCR0_IPE | CCR0_TPE | \ + CCR0_PFC | \ + CCR0_IPP0 | CCR0_IPP1 | \ + CCR0_DPP1) +#endif + + +#ifndef __ASSEMBLER__ + +/// \page noncacheable_support Non-cacheable modes for PgP +/// +/// In order to support evaluation of cache management strategies on +/// performance, DMA buffers read/written by DMA devices can be declared as +/// NONCACHEABLE or NONCACHEABLE_RO, and DMA buffers read by DMA devices can +/// be declared as WRITETHROUGH. However the code still does an explicit +/// FLUSH of these buffers before activating DMA devices. The configuration +/// option NONCACHEABLE_SUPPORT determines how NONCACHEABLE, NONCACAHEABLE_RO, +/// WRITETHROUGH and FLUSH are defined. +/// +/// When noncacheable support is configured, the linker will link the +/// noncacheable and writethrough sections at a fixed offset from cacheable +/// address, depending on where SSX is loaded. Non-cacheable read-only +/// sections are enforced only if PPC405_MMU_SUPPORT is also configured. +/// Writethrogh sections are assumed to be read-write. +/// +/// PGP_HIGH_MEMORY_LOAD +/// +/// cacheable : 0xfff8000 - 0xffffffff +/// noncacheable : 0xf7f8000 - 0xf7ffffff [cacheable - 128MB] +/// writethrough : 0xeff8000 - 0xefffffff [cacheable - 256MB] + + +#ifndef NONCACHEABLE_SUPPORT +#define NONCACHEABLE_SUPPORT 0 +#endif + + +/// Declare an aligned data structure in a noncacheable RO section +/// +/// This macro declares an aligned data structure in a noncacheable read-only +/// section. The linker requires that data allocated in non-default sections +/// be initialized - so an initialization declaration for at least one element +/// of the data structure is required. Use a value of 8 as the default +/// alignment. +/// +/// See \ref noncacheable_support + +#if NONCACHEABLE_SUPPORT + +#define NONCACHEABLE_RO(declaration, alignment, initialization) \ + declaration __attribute__ \ + ((section (".noncacheable_ro"), aligned (alignment))) = initialization + +#else + +#define NONCACHEABLE_RO(declaration, alignment, initialization) \ + declaration __attribute__ \ + ((aligned (alignment))) = initialization + +#endif /* NONCACHEABLE_SUPPORT */ + + +/// Declare an aligned data structure in a noncacheable RW section +/// +/// This macro declares an aligned data structure in a noncacheable read-write +/// section. The linker requires that data allocated in non-default sections +/// be initialized - so an initialization declaration for at least one element +/// of the data structure is required. Use a value of 8 as the default +/// alignment. +/// +/// See \ref noncacheable_support + +#if NONCACHEABLE_SUPPORT + +#define NONCACHEABLE(declaration, alignment, initialization) \ + declaration __attribute__ \ + ((section (".noncacheable"), aligned (alignment))) = initialization + +#else + +#define NONCACHEABLE(declaration, alignment, initialization) \ + declaration __attribute__ \ + ((aligned (alignment))) = initialization + +#endif /* NONCACHEABLE_SUPPORT */ + + +/// Declare an aligned data structure in a write-through section +/// +/// This macro declares an aligned data structure in a write-throgh section. +/// The linker requires that data allocated in non-default sections be +/// initialized - so an initialization declaration for at least one element of +/// the data structure is required. Use a value of 8 as the default +/// alignment. +/// +/// See \ref noncacheable_support + +#if NONCACHEABLE_SUPPORT + +#define WRITETHROUGH(declaration, alignment, initialization) \ + declaration __attribute__ \ + ((section (".writethrough"), aligned (alignment))) = initialization + +#else + +#define WRITETHROUGH(declaration, alignment, initialization) \ + declaration __attribute__ \ + ((aligned (alignment))) = initialization + +#endif /* NONCACHEABLE_SUPPORT */ + + +/// Flush/invalidate a region of memory + +#if NONCACHEABLE_SUPPORT +#define FLUSH(p, n) do {} while (0) +#define INVALIDATE(p, n) do {} while (0) +#else +#define FLUSH(p, n) do {dcache_flush((p), (n));} while (0) +#define INVALIDATE(p, n) do {dcache_invalidate((p), (n));} while (0) +#endif /* NONCACHEABLE_SUPPORT */ + + +/// The type of linker symbols +/// +/// C++ and current GCC versions do not allow us to declare (C++) or take the +/// address of (C) a symbol of type void, which was an acceptable way to +/// declare linker symbols in earlier versions of GCC. However if we declare +/// them of type 'char' or another integral type, the compiler will try to +/// make references to this 'data' appear to be in the small data areas (since +/// we're compiling with the PPC EABI), which causes the link to fail since +/// the symbols are actually defined in many different sections. The solution +/// is to declare them to be external references of a bogus type, +/// SsxLinkerSymbol, which is too large (9 bytes) to be stored in the small +/// data area. +/// +/// This type definition is considered a required definition for a port of +/// SSX. + +typedef struct { + char bogus[9]; +} SsxLinkerSymbol; + +// Symbols defined by linkssx.cmd, used during MMU setup, byte-pool setup, and +// other purposes. + +extern SsxLinkerSymbol _MEMORY_ORIGIN; +extern SsxLinkerSymbol _MEMORY_SIZE; +extern SsxLinkerSymbol _TEXT0_SECTION_BASE; +extern SsxLinkerSymbol _TEXT0_SECTION_SIZE; +extern SsxLinkerSymbol _TEXT1_SECTION_BASE; +extern SsxLinkerSymbol _TEXT1_SECTION_SIZE; +extern SsxLinkerSymbol _RODATA_SECTION_BASE; +extern SsxLinkerSymbol _RODATA_SECTION_SIZE; +extern SsxLinkerSymbol _NONCACHEABLE_RO_SECTION_BASE; +extern SsxLinkerSymbol _NONCACHEABLE_RO_SECTION_SIZE; +extern SsxLinkerSymbol _NONCACHEABLE_SECTION_BASE; +extern SsxLinkerSymbol _NONCACHEABLE_SECTION_SIZE; +extern SsxLinkerSymbol _WRITETHROUGH_SECTION_BASE; +extern SsxLinkerSymbol _WRITETHROUGH_SECTION_SIZE; +extern SsxLinkerSymbol _DATA_SECTION_BASE; +extern SsxLinkerSymbol _DATA_SECTION_SIZE; +extern SsxLinkerSymbol _EX_FREE_SECTION_BASE; +extern SsxLinkerSymbol _EX_FREE_SECTION_SIZE; +extern SsxLinkerSymbol _APPLET0_SECTION_BASE; +extern SsxLinkerSymbol _APPLET0_SECTION_SIZE; +extern SsxLinkerSymbol _APPLET1_SECTION_BASE; +extern SsxLinkerSymbol _APPLET1_SECTION_SIZE; +extern SsxLinkerSymbol _SSX_FREE_START; +extern SsxLinkerSymbol _SSX_FREE_END; + +// Global MMU maps to allow remapping certain regions + +extern Ppc405MmuMap G_ex_free_mmu_map; +extern Ppc405MmuMap G_applet0_mmu_map; +extern Ppc405MmuMap G_applet1_mmu_map; + +#endif /* __ASSEMBLER__ */ + +// PgP defines a private version of dcache_flush_all() that uses the undefined +// OCI space at 0x80000000; See dcache_flush_all() in pgp_cache.S. + +#define USE_GENERIC_DCACHE_FLUSH_ALL 0 +#define PGP_FLUSH_ZERO_ADDRESS 0x80000000 +#define PGP_FLUSH_ZERO_DCCR 0x00008000 + +#endif /* __PGP_H__ */ diff --git a/src/ssx/pgp/pgp_async.c b/src/ssx/pgp/pgp_async.c new file mode 100755 index 0000000..3bf9a63 --- /dev/null +++ b/src/ssx/pgp/pgp_async.c @@ -0,0 +1,1024 @@ +// $Id: pgp_async.c,v 1.4 2014/02/14 12:18:05 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_async.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_async.c +/// \brief Support for asynchronous request queuing and callback mechanisms +/// +/// This file implements device drivers for asynchronous requests. The model +/// for devices like the PORE engines and the PBA block copy engines is that +/// the application creates self-contained requests for jobs to run on the +/// engine. The application then schedules the request and continues normal +/// processing, or threads can request to simply block in place until the +/// request finishes. Queue management is handled in the interrupt handler +/// for the engine. As each queued job finishes, the next request (if any) is +/// started on the engine and the optional callback is invoked or scheduled. +/// +/// The application can either use a polling protocol or the asynchronous +/// callback mechanism to determine the state of the request. A timeout +/// mechanism is also provided that cancels or kills a job that does not +/// complete within a fixed time. Error handling in the event that the request +/// does not complete in time or has failed is standardized by the +/// implementation, but can be overridden by the application. +/// +/// Asynchronous request interrupt handlers can run either as critical or +/// noncritical handlers. Some engines may support queuing requests that +/// complete immediately; therefore the kernel context of the callback may be +/// either a thread or interupt context, and in general, callbacks should not +/// make assumptions about the kernel context when they run. +/// +/// If the callback is non-NULL and the request was created with \c +/// ASYNC_CALLBACK_IMMEDIATE, the callback is then immediately invoked in the +/// current context. In general, immediate callbacks should be short and sweet +/// (to reduce interrupt latency) and should not make SSX kernel calls. +/// +/// If the request has a non-NULL callback and was created with \c +/// ASYNC_CALLBACK_DEFERRED then the callback will be deferred to a +/// noncritical interrupt context. Deferred callbacks are queued, then run +/// later in response to a reserved IPI. Deferred callbacks always run as +/// noncritical interrupt handlers with noncritical interrupts \e enabled, +/// similar to SSX timer callbacks. +/// +/// If the request has a non-null callback and was created with \c +/// ASYNC_CALLBACK_NONCRITICAL, then the callback will be run immediately from +/// a noncritical handler or thread environment, or deferred from a critical +/// interrupt context. Similar to immediate callbacks, callbacks marked +/// noncritical should be short and sweet (to reduce interrupt latency), but +/// may make SSX kernel calls. +/// +/// Regardless of whether the callback is critical or noncritical, the +/// callback is coded as a normal C or assembler subroutine with a single +/// void* argument. +/// +/// As a programming shortcut, the AsyncRequest includes a semaphore object. +/// A special AsyncRequest option ASYNC_REQUEST_BLOCKING indicates that the +/// thread scheduling the request should block on the semaphore of the +/// AsyncRequest (with SSX_WAIT_FOREVER) until the request is complete. Note +/// that a separate callback can be specified even if ASYNC_REQUEST_BLOCKING +/// is specified. +/// +/// Requests are always timestamped. The \a start_time field of the request is +/// set from the SSX timebase when the request is first 'run' on the device. +/// Request types that may require multiple back-to-back 'runs' (like PBA +/// block copies with more than 4K data) only record the initial 'run'. The \a +/// end_time field of the request is set from the SSX timebase when the job +/// finishes on the hardware, but before any callback is run. These +/// timestamps cover time intervals not visible to the application; The +/// application is responsible for timestamping the period between request +/// queing and the \a start_time, and between the \a end_time and callback +/// completion if required. The timestamps can be robustly recovered from the +/// request using the API async_request_timestamps_get(). +/// +/// This is largely a generic implementation, designed to reduce code space by +/// allowing the PORE, PBA and OCB drivers to use the same generic data +/// structures and code. This is supported by the 'single-inheritence class +/// hierarchy' described in the comments for pgp_async.h. +/// +/// <b> Request Completion and Callback States </b> +/// +/// The application can determine what happend to the job by observing the +/// request state and callback return code when the request becomes idle. +/// A request is not considered idle until the job has run to completion or +/// been aborted, any callback has been run, any timeout has been cancelled, +/// and any thread pending on request completion has been maxde runnable. +/// +/// Normally the application should see the request state (\a request->state) +/// ASYNC_REQUEST_STATE_COMPLETE and a callback return code +/// (\a request=->callback_rc) of 0 which indicates that the job and callback +/// both completed normally. If the request did not complete normally it +/// could be due to one of several reasons. For further analysis the request +/// also includes a field \a abort_state that records the state the job was in +/// when it was aborted (i.e., cancelled, killed, timed out or error-out). +/// +/// <b> Timeout Semantics </b> +/// +/// Any timeout other than SSX_WAIT_FOREVER specifies a timeout covering the +/// interval spanning the time a job is scheduled until the time the job +/// completes on the hardware. If the job is still wating to execute when it +/// times out then the job is simply removed from the queue and marked as +/// having timed out. If the job is running when it times out then the job is +/// forceably removed from the hardware, which may have unintended or +/// indeterminate consequences. The application may need to consider whether +/// it is safe to continue after a forced timeout. +/// +/// Specifying a timeout involves quite a bit of overhead, since a timer needs +/// to be scheduled and cancelled each time a job is run. If the interrupt +/// handler for a device is a critical handler then the timeout cancellation +/// will need to be deferred to the callback queue, potentially increasing +/// overhead even further. +/// +/// <b> Implementation Notes </b> +/// +/// - The \e queue objects will normally be global data structures that +/// persist throughout the life of the application. +/// +/// - The \e request objects may be either global or local data +/// structures. However, since \e request objects are not copied, and pointers +/// to them are stored in the \e queue objects, \a request objects should not +/// be allocated on the stack if the stack frame could become invalid before +/// the request completes. +/// +/// \todo Once all function is developed and tested, convert interrupt +/// handling to fast-mode assembler routines. + +#include "ssx.h" + + +//////////////////////////////////////////////////////////////////////////// +// Global Data +//////////////////////////////////////////////////////////////////////////// + +/// Queue of deferred callbacks + +static SsxDeque G_async_callback_queue; + + +//////////////////////////////////////////////////////////////////////////// +// FFDC +//////////////////////////////////////////////////////////////////////////// + +/// Collect FFDC for the PLB (OCI) arbiter +/// +/// \param ffdc A pointer to an OciFfdc structure to be filled in. +/// +/// \param master_id The PLB (OCI) master Id of the master of interest. +/// +/// Note: The PEAR and PESR hold error information for all OCI masters +/// _except_ the OCC ICU and DCU. ICU and DCU errors are in the STO_PESR and +/// STO_PEAR. Currently there is no need to collect those DCRs for 'async' +/// errors. + +void +oci_ffdc(OciFfdc* ffdc, int master_id) +{ + uint32_t pesr_lock_mask; + + ffdc->pearl.value = mfdcr(PLB_PEARL); + ffdc->pesr.value = mfdcr(PLB_PESR); + + pesr_lock_mask = 0x30000000 >> (4 * master_id); + if (ffdc->pesr.value & pesr_lock_mask) { + ffdc->mine = 1; + mtdcr(PLB_PESR, pesr_lock_mask); + } else { + ffdc->mine = 0; + } +} + + + +//////////////////////////////////////////////////////////////////////////// +// AsyncQueue +//////////////////////////////////////////////////////////////////////////// + +// Start an asynchronous request on the device with timestamping. This will +// always be called from a critical section, and any timestamp is collected +// immediately before the request is kicked off on the device. Devices like +// the BCE engines and the OCB queue drivers may run the same request multiple +// times to get all of the data moved. Therefore the initial timestamp is only +// captured the first time the request is run on the device. + +static inline int +async_request_run(AsyncRequest *request) +{ + if (request->state != ASYNC_REQUEST_STATE_RUNNING) { + request->start_time = ssx_timebase_get(); + } + request->state = ASYNC_REQUEST_STATE_RUNNING; + return request->run_method(request); +} + + +// Create (initialize) a generic AsyncQueue +// +// This is an internal API used to initialize generic request queues. The +// caller is assumed to have done all error checking on the parameters. +// +// This is a simple initialization that resets the queues and sets the state +// to QUEUE_STATE_IDLE. This routine should only be called on uninitialized +// AsyncQueue objects. + +int +async_queue_create(AsyncQueue *queue, AsyncEngine engine) +{ + ssx_deque_sentinel_create(&(queue->deque)); + queue->current = 0; + queue->engine = engine; + queue->state = ASYNC_QUEUE_STATE_IDLE; + + return 0; +} + + +// Generic completion of a request. This is called both by async_handler() +// and async_request_deque(). + +static void +async_request_complete(AsyncRequest *request) +{ + SsxMachineContext ctx; + AsyncRequestCallback callback; + int completed; + + // Handle callbacks and deferred processing of the job that just + // finished. No callback is easy. If the job does have a callback + // that we can execute immediately then that is done immediately. + // Note that 'completed' here means only that the callback is complete. + + callback = request->callback; + if (!callback) { + + completed = 1; + + } else if ((request->options & ASYNC_CALLBACK_IMMEDIATE) || + ((request->options & ASYNC_CALLBACK_NONCRITICAL) && + !__ssx_kernel_context_critical_interrupt())) { + + request->state = ASYNC_REQUEST_STATE_CALLBACK_RUNNING; + request->callback_rc = callback(request->arg); + completed = 1; + + } else { + + request->state = ASYNC_REQUEST_STATE_CALLBACK_QUEUED; + completed = 0; + } + + + // If the callback completed then we go ahead and cancel any timeout + // and/or wake the thread if possible. In critical interrupt contexts + // we always have to defer these operations, so we may lose 'complete' + // status. + + if (completed && + ((request->timeout != SSX_WAIT_FOREVER) || + (request->options & ASYNC_REQUEST_BLOCKING))) { + + if (__ssx_kernel_context_critical_interrupt()) { + + request->state = ASYNC_REQUEST_STATE_POSTPROCESSING; + completed = 0; + + } else { + if (request->timeout != SSX_WAIT_FOREVER) { + ssx_timer_cancel(&(request->timer)); + } + if (request->options & ASYNC_REQUEST_BLOCKING) { + ssx_semaphore_post(&(request->sem)); + } + } + } + + + // A truly completed job gets its completion state here. Otherwise we + // have to schedule the deferred postprocessing. + + if (completed) { + + request->state = request->completion_state; + + } else { + + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + + if (request->options & ASYNC_CALLBACK_PRIORITY) { + ssx_deque_push_front(&G_async_callback_queue, + &(request->deque)); + } else { + ssx_deque_push_back(&G_async_callback_queue, + &(request->deque)); + } + + ssx_critical_section_exit(&ctx); + ssx_irq_status_set(PGP_IRQ_ASYNC_IPI, 1); + } +} + + +// The generic handler for asynchonous device completion. +// +// This handler processes completions of generic device requests, as well as +// the initial running of jobs when the queue is idle. Error completions are +// initially handled by async_error_handler() which then calls async_handler() +// to finish the failed job and start the next job if possible. The initial +// device handler must manage interrupts and provide a method to run the +// 'current' job in the queue. The engine-specific handler may also iterate +// the current job until it is complete - this handler should only be called +// when the current job is complete. +// +// Some engines may have jobs that can complete immediately. This handler +// iterates over jobs in the queue as long as the run method of the current +// job returns the code -ASYNC_REQUEST_COMPLETE. +// +// NB : Normally this call is made from an interrupt handler, however it may +// be called from job scheduling code if the engine is idle. Regardless, the +// caller must insure that any call for a queue is protected against +// interrupts for that queue. + +void +async_handler(AsyncQueue *queue) +{ + AsyncRequest *finished, *current; + int rc; + + // This loop is repeated as long as any job started in a loop completes + // immediately. + + do { + + // This API may be called on an idle queue, which indicates that we + // should simply start the job on the head of the queue. Otherwise + // save a pointer to the job that just finished and update its + // end_time. + + if (queue->state == ASYNC_QUEUE_STATE_IDLE) { + + finished = 0; + + } else { + + finished = (AsyncRequest *)(queue->current); + + if (SSX_ERROR_CHECK_KERNEL && (finished == 0)) { + SSX_PANIC(ASYNC_PHANTOM_INTERRUPT); + } + + finished->end_time = ssx_timebase_get(); + + } + + + // If the queue is in an error state we will not schedule any further + // jobs on this queue. Otherwise we start the next job running on the + // engine. + + if (queue->state == ASYNC_QUEUE_STATE_ERROR) { + + queue->current = 0; + rc = 0; + + } else { + + current = (AsyncRequest *)ssx_deque_pop_front(&(queue->deque)); + queue->current = current; + + if (current) { + queue->state = ASYNC_QUEUE_STATE_RUNNING; + rc = async_request_run(current); + } else { + queue->state = ASYNC_QUEUE_STATE_IDLE; + rc = 0; + } + } + + + // If no job just finished, continue with the loop. If the job we + // just enqueued finished immediately it will be 'finished' on the + // next loop (it would have given an rc == + // -ASYNC_REQUEST_COMPLETE). Otherwise complete the request. + + if (finished != 0) { + + async_request_complete(finished); + } + + } while (rc == -ASYNC_REQUEST_COMPLETE); +} + + +/// Schedule (queue for execution) a generic asynchronous request. +/// +/// \param request An initialized and idle AsyncRequest +/// +/// +/// The request is queued for execution with all of the parameters provided +/// when the request was created. It is considered an error to (re)schedule a +/// request that is currently scheduled, running, or has the callback queued or +/// in execution. Requests either need to be idle, or must be explicitly +/// cancelled or killed before thay can be (re)scheduled. Because engine queue +/// interrupt handlers may run as critical interrupts, this routine operates in +/// a short \c SSX_CRITICAL critical section. +/// +/// If the request is made to an otherwise empty queue then the async_handler() +/// must also be called immediately to begin the job. This will extend the +/// critical section slightly. This routine will not start a request on a +/// queue that has halted due to an error. The request will simply be enqueued +/// in that case. +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_OBJECT_SCHEDULE The \a request is NULL (0). +/// +/// \retval -ASYNC_REQUEST_NOT_IDLE The \a request is (still) active in some +/// way at entry. +/// +/// \retval -ASYNC_REQUEST_NOT_COMPLETE This code is returned for requests that +/// do not complete successfully, but only if ASYNC_REQUEST_BLOCKING is +/// specified. The caller will need to examine the request state if necessary +/// to determine whether the request failed, was cancelled or timed out. +/// +/// \todo Consider making the critical section priority depend on the device +/// queue priority here, by adding a priority field to the queue. Without this +/// we always have to run the async_handler() in an SSX_CRITICAL critical +/// section. + +int +async_request_schedule(AsyncRequest *request) +{ + SsxMachineContext ctx = SSX_THREAD_MACHINE_CONTEXT_DEFAULT; // For GCC + AsyncQueue *queue; + int rc; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(request == 0, ASYNC_INVALID_OBJECT_SCHEDULE); + } + + rc = 0; + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + + do { + + // Check to insure the request is idle (which check must be done in + // the critical section), then start any required timeout. + + if (SSX_ERROR_CHECK_API) { + if (!async_request_is_idle(request)) { + rc = -ASYNC_REQUEST_NOT_IDLE; + break; + } + } + + if (request->timeout != SSX_WAIT_FOREVER) { + rc = ssx_timer_schedule(&(request->timer), request->timeout, 0); + if (rc) break; + } + + + // Enqueue the request and initialize the request state. + + queue = request->queue; + + if (request->options & ASYNC_REQUEST_PRIORITY) { + ssx_deque_push_front(&(queue->deque), &(request->deque)); + } else { + ssx_deque_push_back(&(queue->deque), &(request->deque)); + } + + request->state = ASYNC_REQUEST_STATE_QUEUED; + request->completion_state = ASYNC_REQUEST_STATE_COMPLETE; + request->callback_rc = 0; + + + // If the queue is idle, call the async_handler() to start the job. + // Then block the calling thread if required. + + if (queue->state == ASYNC_QUEUE_STATE_IDLE) { + async_handler(queue); + } + + if (request->options & ASYNC_REQUEST_BLOCKING) { + rc = ssx_semaphore_pend(&(request->sem), SSX_WAIT_FOREVER); + if (rc) break; + + if (!async_request_completed(request)) { + rc = -ASYNC_REQUEST_NOT_COMPLETE; + break; + } + } + + } while (0); + + ssx_critical_section_exit(&ctx); + + return rc; +} + + +// The generic error handler +// +// This is a generic handler called in response to an error interrupt or +// timeout. This handler calls a request-specific error method to stop the +// hardware device, collect FFDC and make the hardware device runnable again +// if possible. Then the current request is marked as having failed, and the +// generic async_handler() is called which will start the next job (if any) +// and take care of the callbacks for the failed request. If the error +// method returns a non-0 return code then the error is non-recoverable and +// the queue is marked with the error state. + +void +async_error_handler(AsyncQueue* queue, uint8_t completion_state) +{ + AsyncRequest *finished; + + finished = (AsyncRequest *)(queue->current); + + if (SSX_ERROR_CHECK_KERNEL && (finished == 0)) { + SSX_PANIC(ASYNC_PHANTOM_ERROR); + } + + if (finished->error_method) { + if (finished->error_method(finished)) { + queue->state = ASYNC_QUEUE_STATE_ERROR; + } + } + finished->abort_state = finished->state; + finished->completion_state = completion_state; + async_handler(queue); +} + + +//////////////////////////////////////////////////////////////////////////// +// AsyncRequest +//////////////////////////////////////////////////////////////////////////// + +// Dequeue a queued AsyncRequest +// +// This is an internal API, always called from an SSX_CRITICAL critical +// section. The request is known to be queued in one of the async queues. It +// is removed from the queue and its state is updated. + +static void +async_request_dequeue(AsyncRequest* request, uint8_t completion_state) +{ + ssx_deque_delete((SsxDeque*)request); + request->abort_state = request->state; + request->completion_state = completion_state; + async_request_complete(request); +} + + +// Time out an AsyncRequest +// +// This is an internal API, the timer callback used to time out long-running +// AsyncRequest. +// +// This timer callback must run in an SSX_CRITICAL critical section to +// guarantee atomic access to the AsyncRequest object. + +static void +async_timeout(void* arg) +{ + AsyncRequest *request = (AsyncRequest*)arg; + SsxMachineContext ctx; + + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + + // The behavior at timeout depends on the mode. We'll handle the cases + // from easiest to hardest. + + if (request->state & ASYNC_REQUEST_CALLBACK_GROUP) { + + // If the request has already queued or is running the callback (which + // could happen due to interrupt interleaving) then the request is + // already finished, and it will eventually make a (redundant) call to + // ssx_timer_cancel() to cancel the timer. So there's nothing to do. + + + } else if (request->state & ASYNC_REQUEST_IDLE_GROUP) { + + // If the request is idle we panic - This can't happen as it would + // indicate that the timer was not cancelled when the request + // finished. + + SSX_PANIC(ASYNC_TIMEOUT_BUG); + + + } else if (request->state & ASYNC_REQUEST_QUEUED_GROUP) { + + // If the request is still in the queue then we can simply cancel it, + // which includes running the callback. + + async_request_dequeue(request, ASYNC_REQUEST_STATE_TIMED_OUT); + + + } else if (request->state & ASYNC_REQUEST_RUNNING_GROUP) { + + // If the request is running on the hardware, then we need to call + // the async_error_handler() to remove the job and restart the + // hardware, which includes running the callback. + + async_error_handler(request->queue, ASYNC_REQUEST_STATE_TIMED_OUT); + + + } else { + + SSX_PANIC(ASYNC_INVALID_STATE); + + } + + ssx_critical_section_exit(&ctx); +} + + +// Create (initialize) a generic AsyncRequest +// +// This is an internal API used to initialize generic requests. However this +// API does some error checking, and any errors will be returned by the +// higher-level call. +// +// \retval -ASYNC_INVALID_OBJECT_REQUEST The \a request or \a queue was +/// null (0). +// +// \retval -ASYNC_INVALID_OPTIONS The \a options argument contains invalid +// options, or more than one callback protocol was selected. +// +// \retval -ASYNC_INVALID_ARGUMENT The \a run_method was null. +// +// \retval -ASYNC_CALLBACK_PROTOCOL_UNSPECIFIED The request includes a +// non-NULL callback, but no protocol for running the callback was specified. + +int +async_request_create(AsyncRequest *request, + AsyncQueue *queue, + AsyncRunMethod run_method, + AsyncErrorMethod error_method, + SsxInterval timeout, + AsyncRequestCallback callback, + void *arg, + int options) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((request == 0) || (queue == 0), + ASYNC_INVALID_OBJECT_REQUEST); + SSX_ERROR_IF((options & ~ASYNC_GENERIC_OPTIONS) || + (__builtin_popcount(options & ASYNC_CALLBACK_OPTIONS) > 1), + ASYNC_INVALID_OPTIONS); + SSX_ERROR_IF(run_method == 0, ASYNC_INVALID_ARGUMENT); + SSX_ERROR_IF((callback != 0) && + ((options & ASYNC_CALLBACK_OPTIONS) == 0), + ASYNC_CALLBACK_PROTOCOL_UNSPECIFIED); + } + + ssx_deque_element_create(&(request->deque)); + request->queue = queue; + request->run_method = run_method; + request->error_method = error_method; + request->timeout = timeout; + request->state = ASYNC_REQUEST_STATE_INITIALIZED; + request->callback = callback; + request->arg = arg; + request->options = options; + + if (request->timeout != SSX_WAIT_FOREVER) { + ssx_timer_create(&(request->timer), async_timeout, (void*)request); + } + + if (options & ASYNC_REQUEST_BLOCKING) { + ssx_semaphore_create(&(request->sem), 0, 1); + } + + + return 0; +} + + +/// Get timestamps from an AsyncRequest object +/// +/// \param request A pointer to an AsyncRequest +/// +/// \param start_time A pointer to a location to get the \a start_time of the +/// request, or NULL (0) if this data is not required. +/// +/// \param end_time A pointer to a location to get the \a end_time of the +/// request, or NULL (0) is this data is not required. +/// +/// \retval 0 The request contains valid timestamps and they have been +/// returned. +/// +/// \retval -ASYNC_INVALID_TIMESTAMPS The caller's timestamps have been +/// updated, but the timestamps are fully or partially invalid. This could be +/// due to several reasons: +/// +/// - The request has never been scheduled +/// - The request has been scheduled but has not completed on the device +/// - For space/time reasons, timestamps are not supported + +int +async_request_timestamps_get(AsyncRequest* request, + SsxTimebase* start_time, + SsxTimebase* end_time) +{ + int rc; + SsxMachineContext ctx; + + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + + if (start_time) { + *start_time = request->start_time; + } + if (end_time) { + *end_time = request->end_time; + } + + if ((request->state & ASYNC_REQUEST_IDLE_GROUP) && + (request->state != ASYNC_REQUEST_STATE_INITIALIZED)) { + rc = 0; + } else { + rc = -ASYNC_INVALID_TIMESTAMPS; + } + + ssx_critical_section_exit(&ctx); + + return rc; +} + + +/// Compute the latency of an AsyncRequest +/// +/// \param request A pointer to an AsyncRequest +/// +/// \param latency A pointer to a location to receive the latency (end time - +/// start time) computed from the timestamps of \a request. +/// +/// \retval 0 The request contains valid timestamps and they have been +/// returned. +/// +/// \retval -ASYNC_INVALID_TIMESTAMPS The latancy has been computed but may be +/// invalid. This could be due to several reasons: +/// +/// - The request has never been scheduled +/// - The request has been scheduled but has not completed on the device +/// - For space/time reasons, timestamps are not supported + +int +async_request_latency(AsyncRequest* request, SsxTimebase* latency) +{ + int rc; + SsxTimebase start, end; + + rc = async_request_timestamps_get(request, &start, &end); + *latency = end - start; + return rc; +} + + +// Dump an AsyncRequest + +void +async_request_printk(AsyncRequest *request) +{ + printk("----------------------------------------\n"); + printk("-- AsyncRequest @ %p\n", request); + printk("-- deque = %p\n", &(request->deque)); + printk("-- start_time = 0x%016llx\n", request->start_time); + printk("-- end_time = 0x%016llx\n", request->end_time); + printk("-- sem = %p\n", &(request->sem)); + printk("-- queue = %p\n", request->queue); + printk("-- run_method = %p\n", request->run_method); + printk("-- error_method = %p\n", request->error_method); + printk("-- callback = %p\n", request->callback); + printk("-- arg = %p\n", request->arg); + printk("-- state = 0x%02x\n", request->state); + printk("-- completion_state = 0x%02x\n", request->completion_state); + printk("-- options = 0x%04x\n", request->options); + printk("----------------------------------------\n"); +} + + +//////////////////////////////////////////////////////////////////////////// +// Callback Queue +//////////////////////////////////////////////////////////////////////////// + +SSX_IRQ_FAST2FULL(async_callback_handler, async_callback_handler_full); + +// The handler for the asynchronous callback queue +// +// This is a full-mode noncritical interrupt handler. It is activated to run +// 1) all deferred callbacks, and 2) noncritical callbacks invoked from +// critical interrupt handlers, and 3) Thread-unblock and/or timeout-cancel +// requests that needed to be deferred to a noncritical context. The callback +// is enqueued in the SsxDeque passed as the private argument, and an IPI is +// used to activate this handler. +// +// This handler runs each callback in order. Since the callback queue may be +// managed by critical interrupt handlers we need to disable critical +// interrupts when popping the next element from the queue. +// +// Deferred callbacks are run with noncritical interrupts \e enabled, similar +// to how timer callbacks are run. +// +// Noncritical callbacks that were deferred here (by being invoked from a +// critical handler) run with interrupts \e disabled, to be consistent with +// the expected environment. Interrupts are then renabled briefly for +// interrupt latency mitigation. +// +// Note that NULL callbacks may be enqueued here but only in the state +// ASYNC_REQUEST_STATE_POSTPROCESSING. + +// The handler runs with its own IRQ disabled to avoid infinite interrupt +// loops caused by enabling interrupt preemption. The IRQ status can only be +// cleared inside an SSX_CRITICAL critical section. For efficiency we only do +// this when we know that no more callbacks are queued. + +// Final request completion has been broken out into a generic routine, +// async_request_finalize(). This routine is also called by the PTS +// completion queue handler, which handles its requests ion a slightly +// different way from the other async handlers. + +void +async_request_finalize(AsyncRequest* request) +{ + if (request->state == ASYNC_REQUEST_STATE_CALLBACK_QUEUED) { + + request->state = ASYNC_REQUEST_STATE_CALLBACK_RUNNING; + + if (request->options & ASYNC_CALLBACK_DEFERRED) { + + ssx_interrupt_preemption_enable(); + request->callback_rc = request->callback(request->arg); + + } else { + + request->callback_rc = request->callback(request->arg); + ssx_interrupt_preemption_enable(); + } + ssx_interrupt_preemption_disable(); + } + + request->state = request->completion_state; + + if (request->timeout != SSX_WAIT_FOREVER) { + ssx_timer_cancel(&(request->timer)); + } + + if (request->options & ASYNC_REQUEST_BLOCKING) { + ssx_semaphore_post(&(request->sem)); + } +} + + +void +async_callback_handler_full(void *arg, SsxIrqId irq, int priority) +{ + SsxMachineContext ctx; + SsxDeque *queue = (SsxDeque *)arg; + AsyncRequest *request; + + ssx_irq_disable(irq); + + do { + + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + + request = (AsyncRequest *)ssx_deque_pop_front(queue); + if (!request) { + ssx_irq_status_clear(irq); + break; + } + + ssx_critical_section_exit(&ctx); + + async_request_finalize(request); + + } while (1); + + ssx_critical_section_exit(&ctx); + ssx_irq_enable(irq); +} + + +//////////////////////////////////////////////////////////////////////////// +// Initialization +//////////////////////////////////////////////////////////////////////////// + +// These initialization routines are for boot-time initialization, or +// test-mode reinitialization of interface parameters when the interface is +// known to be idle. They are not robust enough for mid-application +// reset/reprogramming of the asynchronous interfaces in the event of errors. + +// For the interrupt setup, whether or not the interrupt is enabled at the +// exit of setup depends on the particular driver being initialized. + +void +async_edge_handler_setup(SsxIrqHandler handler, + void *arg, + SsxIrqId irq, + int priority) +{ + ssx_irq_disable(irq); + ssx_irq_setup(irq, + SSX_IRQ_POLARITY_ACTIVE_HIGH, + SSX_IRQ_TRIGGER_EDGE_SENSITIVE); + ssx_irq_handler_set(irq, handler, arg, priority); + ssx_irq_status_clear(irq); +} + + +void +async_level_handler_setup(SsxIrqHandler handler, + void *arg, + SsxIrqId irq, + int priority, + int polarity) +{ + ssx_irq_disable(irq); + ssx_irq_setup(irq, + polarity, + SSX_IRQ_TRIGGER_LEVEL_SENSITIVE); + ssx_irq_handler_set(irq, handler, arg, priority); +} + + +void +async_callbacks_initialize(SsxDeque *queue, SsxIrqId irq) +{ + ssx_deque_sentinel_create(queue); + async_edge_handler_setup(async_callback_handler, + (void *)queue, + irq, SSX_NONCRITICAL); + ssx_irq_enable(irq); +} + + +/// Create all of the PgP asynchronous request structures and install and +/// activate the interrupt handlers. + +void +async_initialize() +{ + // This is the callback queue used e.g. when critical interrupts need to + // run non-critical callbacks. + + async_callbacks_initialize(&G_async_callback_queue, PGP_IRQ_ASYNC_IPI); + + // PORE + + async_pore_initialize(&G_pore_gpe0_queue, ASYNC_ENGINE_PORE_GPE0); + async_pore_initialize(&G_pore_gpe1_queue, ASYNC_ENGINE_PORE_GPE1); + async_pore_initialize(&G_pore_slw_queue, ASYNC_ENGINE_PORE_SLW); + +#if CONFIGURE_PTS + // PTS + + async_pts_initialize(&G_pts_gpe0_queue, ASYNC_ENGINE_PORE_GPE0); + async_pts_initialize(&G_pts_gpe1_queue, ASYNC_ENGINE_PORE_GPE1); +#endif + + // BCE + + async_bce_initialize(&G_pba_bcde_queue, + ASYNC_ENGINE_BCDE, + PGP_IRQ_PBA_BCDE_ATTN); + + async_bce_initialize(&G_pba_bcue_queue, + ASYNC_ENGINE_BCUE, + PGP_IRQ_PBA_BCUE_ATTN); + + // OCB + + async_ocb_initialize(&(G_ocb_read_queue[0]), + ASYNC_ENGINE_OCB_PUSH0, + G_ocb_read0_buffer, + OCB_READ0_LENGTH, + OCB_READ0_PROTOCOL); + + async_ocb_initialize(&(G_ocb_read_queue[1]), + ASYNC_ENGINE_OCB_PUSH1, + G_ocb_read1_buffer, + OCB_READ1_LENGTH, + OCB_READ1_PROTOCOL); + + async_ocb_initialize(&(G_ocb_read_queue[2]), + ASYNC_ENGINE_OCB_PUSH2, + G_ocb_read2_buffer, + OCB_READ2_LENGTH, + OCB_READ2_PROTOCOL); + + async_ocb_initialize(&(G_ocb_write_queue[0]), + ASYNC_ENGINE_OCB_PULL0, + G_ocb_write0_buffer, + OCB_WRITE0_LENGTH, + OCB_WRITE0_PROTOCOL); + + async_ocb_initialize(&(G_ocb_write_queue[1]), + ASYNC_ENGINE_OCB_PULL1, + G_ocb_write1_buffer, + OCB_WRITE1_LENGTH, + OCB_WRITE1_PROTOCOL); + + async_ocb_initialize(&(G_ocb_write_queue[2]), + ASYNC_ENGINE_OCB_PULL2, + G_ocb_write2_buffer, + OCB_WRITE2_LENGTH, + OCB_WRITE2_PROTOCOL); + + // PBAX + + async_pbax_initialize(&G_pbax_read_queue[0], + ASYNC_ENGINE_PBAX_PUSH0, + PGP_IRQ_PBA_OCC_PUSH0, + G_pbax_read0_buffer, + PBAX_READ0_LENGTH, + PBAX_READ0_PROTOCOL); + + async_pbax_initialize(&G_pbax_read_queue[1], + ASYNC_ENGINE_PBAX_PUSH1, + PGP_IRQ_PBA_OCC_PUSH1, + G_pbax_read1_buffer, + PBAX_READ1_LENGTH, + PBAX_READ1_PROTOCOL); +} diff --git a/src/ssx/pgp/pgp_async.h b/src/ssx/pgp/pgp_async.h new file mode 100755 index 0000000..ecd3ae2 --- /dev/null +++ b/src/ssx/pgp/pgp_async.h @@ -0,0 +1,1654 @@ +#ifndef __PGP_ASYNC_H__ +#define __PGP_ASYNC_H__ + +// $Id: pgp_async.h,v 1.2 2014/02/03 01:30:34 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_async.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_async.h +/// \brief Support for asynchronous request/callback mechanisms +/// +/// The data structures defined here provide a 'C' implementation of multiple +/// single-inheritance class hierarchies. The 'subclasses' always include the +/// 'superclass' as the initial element of the structure, allowing subclass +/// pointers to be safely cast to the superclass, and vice-versa (assuming +/// that the subclass is known). One benefit of this approach is that it +/// allows code sharing between requests targeting PORE-GPE, PORE-SW, +/// PBA-BCDE, PBA-BCUE and the deferred callback queue. +/// +/// The 'class hierarchy' : +/// +/// SsxDeque +/// AsyncRequest +/// PoreRequest +/// PoreFixed +/// PoreFlex +/// BceRequest +/// OcbRequest +/// Pbaxrequest +/// +/// AsyncQueue +/// PoreQueue +/// BceQueue +/// OcbQueue +/// PbaxQueue +/// +/// \bug We may need to redo how we start jobs since writing the EXE-TRIGGER +/// does not guarantee a restart from a good state, although if we get our CCB +/// request through it will. + + +// PgP Execution engines for the purposes of the generic request mechanism. + +#define ASYNC_ENGINE_ANONYMOUS 0x00 + +#define ASYNC_ENGINE_PORE 0x10 +#define ASYNC_ENGINE_PORE_GPE0 0x10 +#define ASYNC_ENGINE_PORE_GPE1 0x11 +#define ASYNC_ENGINE_PORE_SLW 0x12 + +#define ASYNC_ENGINE_BCE 0x20 +#define ASYNC_ENGINE_BCDE 0x20 +#define ASYNC_ENGINE_BCUE 0x21 + +// Indirect channel 3 no longer supports push/pull queues and they have been +// removed. +#define ASYNC_ENGINE_OCB 0x40 +#define ASYNC_ENGINE_OCB_PUSH0 0x41 +#define ASYNC_ENGINE_OCB_PUSH1 0x42 +#define ASYNC_ENGINE_OCB_PUSH2 0x43 +#define ASYNC_ENGINE_OCB_PULL0 0x45 +#define ASYNC_ENGINE_OCB_PULL1 0x46 +#define ASYNC_ENGINE_OCB_PULL2 0x47 + +#define ASYNC_ENGINE_PBAX 0x80 +#define ASYNC_ENGINE_PBAX_PUSH0 0x81 +#define ASYNC_ENGINE_PBAX_PUSH1 0x82 + + +#ifndef __ASSEMBLER__ + +typedef uint8_t AsyncEngine; + +#endif /* __ASSEMBLER__ */ + + +//////////////////////////////////////////////////////////////////////////// +// FFDC Structures +//////////////////////////////////////////////////////////////////////////// + +#ifndef __ASSEMBLER__ + +/// FFDC from the PLB (OCI) arbiter +/// +/// The PLB arbiter records errors from all OCI masters, including the address +/// of the transaction that caused the error. The PLB arbiter is set up to +/// 'lock' the first error data until the lock is reset. This structure is +/// included in all of the unit FFDC structures for peripherals that can +/// master on the OCI (SLW/GPE/OCB/PBA). Note that OCI errors from the 405 +/// core will cause an immediate machine check exception. + +typedef struct { + + /// PLB arbiter Error Address Register Low + /// + /// This is the address of the last PLB timeout or other error recorded in + /// the PEARL. This is an error for the unit in question only if the + /// \a mine data member is non-zero. + plb_pearl_t pearl; + + /// PLB arbiter Error Status Register + /// + /// The PESR at the time of the error. + plb_pesr_t pesr; + + /// Is the unit in question responsible for the error address recorded in + /// the PEARL? + int mine; + +} OciFfdc; + +void +oci_ffdc(OciFfdc* ffdc, int master_id); + +#endif // __ASSEMBLER__ + + +//////////////////////////////////////////////////////////////////////////// +// AsyncRequest +//////////////////////////////////////////////////////////////////////////// + +/// \defgroup async_request_states ASYNC Request States +/// +/// Request states for async requests are group into 5 logical states for +/// error handling and timeout handling purposes. +/// +/// - Queued Group : Queued requests are still waiting to execute in the device queue, +/// so these requests can be cancelled simply by removing them from the queue. +/// +/// - Running Group : Running requests are running on the hardware, so killing +/// these jobs may require a forced stop and restart of the device. +/// +/// - Callback Group : By specification callbacks are always run if provided, +/// even if a job dies or is timed out. This includes post-processing only +/// work like unblocking blocked threads. These processes are not interrupted. +/// +/// - Idle Group : These jobs are no longer in process, and their states are +/// final. +/// +/// Only idle requests can be (re)scheduled. Only jobs in the Queued or +/// Running states can time out. Once the job has moved to the Callback group +/// it is considered complete as far as timeout processing is concerned. +/// +/// @{ + +/// The request is waiting in the queue +#define ASYNC_REQUEST_STATE_QUEUED 0x10 + + +/// The request is running on the hardware +#define ASYNC_REQUEST_STATE_RUNNING 0x20 + + +/// The request is complete but a deferred callback has yet to run +#define ASYNC_REQUEST_STATE_CALLBACK_QUEUED 0x40 + +/// The request callback is running +#define ASYNC_REQUEST_STATE_CALLBACK_RUNNING 0x41 + +/// Thread unblocking and/or timeout cancellation has been deferred to a +/// noncritical interrupt context. +#define ASYNC_REQUEST_STATE_POSTPROCESSING 0x42 + + +/// The request has been initialized but never run +#define ASYNC_REQUEST_STATE_INITIALIZED 0x80 + +/// The request failed due to an error signalled by hardware +#define ASYNC_REQUEST_STATE_FAILED 0x81 + +/// The request completed normally +#define ASYNC_REQUEST_STATE_COMPLETE 0x82 + +/// The application cancelled the request +#define ASYNC_REQUEST_STATE_CANCELLED 0x83 + +/// The request timed out +#define ASYNC_REQUEST_STATE_TIMED_OUT 0x84 + + +#define ASYNC_REQUEST_QUEUED_GROUP 0x10 +#define ASYNC_REQUEST_RUNNING_GROUP 0x20 +#define ASYNC_REQUEST_CALLBACK_GROUP 0x40 +#define ASYNC_REQUEST_IDLE_GROUP 0x80 + +/// @} + + +/// \defgroup async_request_options ASYNC Request Options +/// +/// These are the option flags for the \a options field of the AsyncRequest. +/// These are generic options applicable to all requests. +/// +/// @{ + +#define ASYNC_CALLBACK_IMMEDIATE 0x0001 +#define ASYNC_CALLBACK_DEFERRED 0x0002 +#define ASYNC_CALLBACK_NONCRITICAL 0x0004 +#define ASYNC_CALLBACK_OPTIONS 0x0007 + +#define ASYNC_REQUEST_PRIORITY 0x0008 +#define ASYNC_CALLBACK_PRIORITY 0x0010 + +#define ASYNC_REQUEST_BLOCKING 0x0020 + +#define ASYNC_GENERIC_OPTIONS 0x003f + +/// @} + +#ifndef __ASSEMBLER__ + +struct AsyncRequest; +struct AsyncQueue; + +typedef int (*AsyncRunMethod)(struct AsyncRequest *request); + +typedef int (*AsyncErrorMethod)(struct AsyncRequest *request); + +typedef int (*AsyncRequestCallback)(void *); + +/// A generic request for the asynchronous request drivers +/// +/// Note: Normally the application will not explicitly manipulate this +/// structure, but will instead manipulate derived structures. +/// +/// A request is queued for a particular engine, with a callback to be +/// executed once the request has been processed by the engine. The \a +/// callback may be NULL, but at a minimum the requestor can observe the \a +/// state of the request to determine the state of request processing. If a +/// deferred callback is requested, then once processing is done the generic +/// handler will requeue the request in a callback queue. +/// +/// The \a run_method is a "pure virtual" function of this class. The \a +/// run_method encapsulates the procedure for starting a job on the +/// engine. The \a run_method may make assumptions about and use data +/// contained in the AsyncQueue class used to queue the requests. +/// +/// The \a error_method is also "pure virtual" function of this class. The \a +/// error_method encapsulates the procedure for collecting FFDC and preparing +/// the engine to run the next job. The \a error_method may make assumptions +/// about and use data contained in the AsyncQueue class used to queue the +/// requests. If the \a error_method returns a non-0 code then the error is +/// considered fatal and the queue stops. + +typedef struct AsyncRequest { + + /// Generic queue management - the "base class" + SsxDeque deque; + + /// The time the job was started on the hardware. + /// + /// For jobs requiring multiple passes on the hardware, e.g., BCE jobs + /// that move more data than the PBA supports with a single pass, this + /// time is the time the first hardware pass started. In this case the + /// interval time computed as the difference with \a start_time includes + /// interrupt handling overhead required to process the completion/restart + /// of intermediate passes. + /// + /// This timestamp is inserted into the request by the generic routine + /// async_request_run(). + SsxTimebase start_time; + + /// The time the job finished on the hardware. + /// + /// This timestamp is inserted into the request by the generic routine + /// async_handler(). + SsxTimebase end_time; + + /// A semaphore for thread-mode requests to block on if desired. + SsxSemaphore sem; + + /// A timer used for timeout management + SsxTimer timer; + + /// The engine queue the request is/was scheduled on + struct AsyncQueue *queue; + + /// The "virtual" run method for the class + AsyncRunMethod run_method; + + /// The "virtual" error handler method for the class + AsyncErrorMethod error_method; + + /// The routine Called (or deferred) with the \a arg parameter once + /// the engine has completed the request. + /// + /// The callback may be NULL (0), in which case the \a arg parameter + /// is ignored, and the only status available to the requestor is the + /// request \a state. + AsyncRequestCallback callback; + + /// The argument of the callback + void *arg; + + /// The timeout value + /// + /// AsyncRequest objects with \a timeout other than SSX_WAIT_FOREVER are + /// governed by a private watchdog timer that will cancel a queued job or + /// kill a running job if the hardware operation does not complete before + /// it times out. + SsxInterval timeout; + + /// The return value of the callback (if any) is stored here + /// + /// The success or failure of the callback is recorded here; it is not + /// recorded in the \a state variable. If there is no callback this field + /// will always read as 0 at job completion. + int callback_rc; + + /// Options controlling request processing + uint8_t options; + + /// The current state of the request + /// + /// This field is declared volatile because applications may poll this + /// field which is set asynchronously by the async interrupt handlers, and + /// optimizing compilers transform polling a variable into an infinite + /// loop if the variable is not set on the initial test! + volatile uint8_t state; + + /// The state of the request when the request was aborted + /// + /// This field is valid when the state of the request is read as + /// ASYNC_REQUEST_STATE_FAILED, ASYNC_REQUEST_STATE_CANCELLED, or + /// ASYNC_REQUEST_STATE_TIMED_OUT. This field records the state of the + /// job when it was forceably cancelled or killed either due to the + /// application's request or due to a hardware error or timeout. + uint8_t abort_state; + + /// The completion state of the request. + /// + /// This is the state that will be reported when the request completes and + /// the callback has been run. Normally this is + /// ASYNC_REQUEST_STATE_COMPLETE. However the specification requires that + /// even jobs that terminate due to an errors, timeouts or being cancelled + /// or killed must run their callbacks. In this case this variable will be + /// set to ASYNC_REQUEST_STATE_FAILED, ASYNC_REQUEST_STATE_TIMED_OUT, + /// ASYNC_REQUEST_STATE_CANCELLED or ASYNC_REQUEST_STATE_KILLED + /// respectively. + uint8_t completion_state; + +} AsyncRequest; + + +int +async_request_create(AsyncRequest *request, + struct AsyncQueue *queue, + AsyncRunMethod run_method, + AsyncErrorMethod error_method, + SsxInterval timeout, + AsyncRequestCallback callback, + void *arg, + int options); + +void +async_request_finalize(AsyncRequest* request); + + +/// Check that an asynchronous request is idle +/// +/// \param request An initialized request +/// +/// A request is considered idle if it is not attached to any of the +/// asynchronous request queues, \e or the request has terminated with an +/// error. This includes requests that have never been scheduled, have +/// completed or been cancelled or killed. Only idle requests can be +/// rescheduled. +/// +/// \retval 0 The request is not idle +/// +/// \retval 1 The request is idle + +static inline int +async_request_is_idle(AsyncRequest *request) +{ + return (request->state & ASYNC_REQUEST_IDLE_GROUP) != 0; +} + + +/// Check an asynchronous request for successful completion +/// +/// \param request A request that had been previosuly scheduled +/// +/// Note that a request is not considered complete until both the engine job +/// has finshed without error and any callback has run to completion. Thus +/// jobs that have error-ed out, been cancelled or killed will be idle (and +/// rescheduleable), but not complete. +/// +/// \retval 0 The request has not yet completed successfully +/// +/// \retval 1 The request has completed successfully. + +static inline int +async_request_completed(AsyncRequest *request) +{ + return (request->state == ASYNC_REQUEST_STATE_COMPLETE); +} + + +int +async_request_timestamps_get(AsyncRequest* request, + SsxTimebase* start_time, + SsxTimebase* end_time); + +int +async_request_latency(AsyncRequest* request, SsxTimebase* latency); + + +void +async_request_printk(AsyncRequest *request); + + +#endif /* __ASSEMBLER__ */ + + +//////////////////////////////////////////////////////////////////////////// +// AsyncQueue +//////////////////////////////////////////////////////////////////////////// + +#define ASYNC_QUEUE_STATE_IDLE 0x00 +#define ASYNC_QUEUE_STATE_RUNNING 0x01 +#define ASYNC_QUEUE_STATE_ERROR 0x02 + +#ifndef __ASSEMBLER__ + +/// A generic asynchronous request queue +/// +/// Note: This structure is normally not manipulated directly by application +/// code, but only by the device drivers. +/// +/// Request queues support 2 priorities - Normal and High. Normal priority +/// requests are queued FIFO order, while high-priority requests are queued +/// LIFO order. Requests queued with high priority always execute before any +/// queued with normal priority, however there is no concept of preemption of +/// a currently running request. +/// +/// Because high-priority requests are queued in LIFO order, multiple +/// high-priority jobs will run in the reverse order from which they were +/// enqueued. + +typedef struct AsyncQueue { + + /// The sentinel of the request queue + SsxDeque deque; + + /// The currently running request, or NULL (0) + AsyncRequest* current; + + /// The engine associated with the queue. + AsyncEngine engine; + + /// The state of the queue + uint8_t state; + +} AsyncQueue; + + +int +async_queue_create(AsyncQueue* queue, AsyncEngine engine); + +void +async_handler(AsyncQueue* queue); + +int +async_request_schedule(AsyncRequest* request); + +void +async_error_handler(AsyncQueue* queue, uint8_t completion_state); + +#endif /* __ASSEMBLER__ */ + + +//////////////////////////////////////////////////////////////////////////// +// Async Initialization +//////////////////////////////////////////////////////////////////////////// + +#ifndef __ASSEMBLER__ + +void +async_edge_handler_setup(SsxIrqHandler handler, + void *arg, + SsxIrqId irq, + int priority); + +void +async_level_handler_setup(SsxIrqHandler handler, + void *arg, + SsxIrqId irq, + int priority, + int polarity); + +void +async_callbacks_initialize(SsxDeque *queue, SsxIrqId irq); + + +#endif // __ASSEMBLER__ + + +//////////////////////////////////////////////////////////////////////////// +// PoreRequest +//////////////////////////////////////////////////////////////////////////// + +#ifndef __ASSEMBLER__ + +struct PoreQueue; + +/// PORE FFDC +/// +/// The PORE engine has 208 bytes of programmer-visible state - too much to +/// allocate in every PoreRequest on the off-chance that a request may fail. +/// This PoreFfdc structure is designed to capture a reasonble amount of data +/// in the case of failure of a PoreFlex request, which does not include any +/// PORE error handlers. This structure is currently 48 bytes. +/// +/// The most common recoverable errors are expected to be erroneous PIB +/// responses from deconfigured (garded) cores. These will show up as Error +/// event 0 and can be debugged from the debug registers. We also include the +/// instruction buffer registers to help debug error 2 - instruction +/// fetch/decode errors. +/// +/// To get a full picture in the event of OCI execution phase errors (error +/// 1), the PORE memory-space address registers are captured. We also capture +/// FFDC from the PLB arbiter, which can be used to debug illegal address-type +/// problems. + +typedef struct { + + /// FFDC from the PLB (OCI) arbiter + OciFfdc oci_ffdc; + + /// PORE Debug Registers + /// + /// - [0] Contains PIB address and PIB return code + /// - [1] Contains failing PC and error status bits + uint64_t debug[2]; + + /// PORE Memory-space address registers. + /// + /// We only save the low-order 32 bits of each - the high-order bits are + /// implied/ignored for OCI-attached engines. If OCC managed the SBE then + /// we would require the high-order bits in an FFDC dump. + uint32_t address[2]; + + /// PORE Instruction buffer 0-2 + /// + /// - [0] Contains the opcode and register/short operands + /// - [1:2] Contain the 64-bit immediate + uint32_t ibuf[3]; + +} PoreFfdc; + + +/// A PORE branch immediate address instruction, used in PORE jump tables. +typedef struct { + uint32_t word[3]; +} PoreBraia; + + +void +pore_braia_create(PoreBraia* instr, uint32_t address); + + +/// A request to run a PORE program +/// +/// A PORE request extends the generic AsyncRequest request by the addition of +/// several fields required to be set up in the engine before the job is run, +/// including the program parameter for the routine. The PoreRequest is an +/// internal class that is re-typed to create the PoreFixed and PoreFlex +/// request classes, which differ only slightly in their behavior. +/// +/// As long as the request is known to be idle the application is free to +/// change the \a parameter value between executions of the PORE program, +/// e.g., to do ping-pong buffer management. None of the other fields should +/// be directly modified by the application. + +typedef struct { + + /// The generic request + AsyncRequest request; + + /// Error information + PoreFfdc ffdc; + + /// The PORE Jump Table + PoreBraia* table; + + /// The initial value of the high-order 32 bits of the ERROR_MASK register + uint32_t error_mask; + + /// The entry point address of the routine. + /// + /// For PoreFlex this entry point will be non-0 and will be inserted into + /// D0, as PoreFlex jobs are kicked off by BRAD. For PoreFixed this + /// parameter will be zero and ignored. + uint32_t entry_point; + + /// The single parameter of the PORE program - EXE-Trigger[32:63] + uint32_t parameter; + + /// The high-order 32 bits of EXE-Trigger used to kick off the program. + /// + /// For PoreFlex this field is always 0, as PoreFlex only uses table entry + /// 0 which contains a BRAD. For PoreFixed this encodes the address of + /// the table entry to kick off. + uint32_t exe_trigger; + +} PoreRequest; + + +typedef PoreRequest PoreFlex; + +typedef PoreRequest PoreFixed; + +int +pore_run_method(AsyncRequest* request); + +int +pore_error_method(AsyncRequest* request); + +#endif /* __ASSEMBLER__ */ + +/// The (fixed) number of PORE jump table error handler slots +#define PORE_ERROR_SLOTS 5 + +/// The maximum number of PORE jump table EXE_TRIGGER slots +#define PORE_TRIGGER_SLOTS 16 + +/// Compute the address of error handler BRAIA entry n of a PORE branch table +#define PORE_ERROR_BRANCH(table, n) ((table) + ((n) * 12)) + +/// Compute the address of entry point BRAIA entry n of a PORE branch table +#define PORE_ENTRY_BRANCH(table, n) \ + ((table) + (((PORE_ERROR_SLOTS) + (n)) * 12)) + + +//////////////////////////////////////////////////////////////////////////// +// PoreFlex +//////////////////////////////////////////////////////////////////////////// + +#ifndef __ASSEMBLER__ + +int +pore_flex_create(PoreFlex* request, + struct PoreQueue* queue, + PoreEntryPoint entry_point, + uint32_t parameter, + SsxInterval timeout, + AsyncRequestCallback callback, + void *arg, + int options); + + +/// See async_request_schedule() for documentation. +static inline int +pore_flex_schedule(PoreFlex* request) +{ + return async_request_schedule((AsyncRequest *)request); +} + +#endif /* __ASSEMBLER__ */ + + +//////////////////////////////////////////////////////////////////////////// +// PoreFixed +//////////////////////////////////////////////////////////////////////////// + +#ifndef __ASSEMBLER__ + +int +pore_fixed_create(PoreFixed *request, + struct PoreQueue *queue, + PoreBraia* table, + uint32_t error_mask, + int start_vector, + uint32_t parameter, + SsxInterval timeout, + AsyncRequestCallback callback, + void *arg, + int options); + +/// See async_request_schedule() for documentation. +static inline int +pore_fixed_schedule(PoreFixed *request) +{ + return async_request_schedule((AsyncRequest *)request); +} + +#endif /* __ASSEMBLER__ */ + + +//////////////////////////////////////////////////////////////////////////// +// PoreQueue +//////////////////////////////////////////////////////////////////////////// + +#ifndef __ASSEMBLER__ + +/// A PORE engine queue +/// +/// A PORE queue consists of a generic AsyncQueue to manage jobs on the +/// engine, the OCI base address of the PORE control register space of the +/// engine, and interrupt information. + +typedef struct PoreQueue { + + /// The generic request queue - the "base class" + AsyncQueue queue; + + /// The base address of the OCI control register space for this engine. + uint32_t oci_base; + + /// The IRQ associated with normal completion on the engine + /// + /// \todo Due to header reference ordering we can't define this as SsxIrqId + uint8_t irq; + + /// The IRQ associated with error completion on the engine + /// + /// \todo Due to header reference ordering we can't define this as SsxIrqId + uint8_t error_irq; + + /// The OCI master number of this engine; See pore_error_method() + uint8_t oci_master; + +} PoreQueue; + + +int +pore_queue_create(PoreQueue *queue, + int engine); + +#endif /* ASSEMBLER */ + + +//////////////////////////////////////////////////////////////////////////// +// PBA FFDC Structures +//////////////////////////////////////////////////////////////////////////// + +#ifndef __ASSEMBLER__ + +/// Common FFDC collected for each PBA subunit in the event that a particular +/// subunit is implicated in an error. This structure contains generic +/// data that may be useful in diagnosing any PBA error. Instances of this +/// structure are embedded in higher-level structures for the PBA bridge, BCE +/// engines, and PBAX mechanism. + +typedef struct { + + /// FFDC from the PLB (OCI) arbiter + OciFfdc oci_ffdc; + + /// The PBA MODE register + pba_mode_t mode; + + /// The PBA FIR + pba_fir_t fir; + + /// PBA Error Report 0 + pba_errpt0_t errpt0; + + /// PBA Error Report 1 + pba_errpt1_t errpt1; + + /// PBA Error Report 2 + pba_errpt2_t errpt2; + + /// PBA Read Buffer Valid Status + pba_rbufvaln_t rbufval[PBA_READ_BUFFERS]; + + /// PBA Write Buffer Valid Status + pba_wbufvaln_t wbufval[PBA_WRITE_BUFFERS]; + + /// PBA BARs + pba_barn_t bar[PBA_BARS]; + + /// PBA BAR masks + pba_barmskn_t barmsk[PBA_BARS]; + + /// Error status - non-0 if this structure contains error data + int error; + +} PbaCommonFfdc; + + +/// FFDC collected for generic PBA bridge errors +/// +/// These types of errors will almost certainly be attributable to the +/// PORE-SLW or PORE-GPE, since the OCC is normally not allowed to perform +/// direct bridge operations after OCC initialization. This structure extends +/// the common PBA FFDC with information on how the slaves were programmed. + +typedef struct { + + /// Common FFDC + PbaCommonFfdc common; + + /// PBA Slave reset register + pba_slvrst_t slvrst; + + /// PBA Slave control registers + pba_slvctln_t slvctl[PBA_SLAVES]; + +} PbaBridgeFfdc; + + +/// FFDC collected for the PBA BCUE/BCDE +/// +/// The BCDE/BCUE control and status registers have identical layouts. +/// Similar to the way the drivers are coded, the BCDE register forms are used +/// to declare the structures. + +typedef struct { + + /// Common FFDC + PbaCommonFfdc common; + + /// BCE control register + pba_bcde_ctl_t ctl; + + /// BCE setup register + pba_bcde_set_t set; + + /// BCE PowerBus setup register + pba_bcde_pbadr_t pbadr; + + /// BCE status register + pba_bcde_stat_t stat; + +} BceFfdc; + + +/// FFDC collected for PBAX send errors + +typedef struct { + + /// Common FFDC + PbaCommonFfdc common; + + /// PBAX configuration register + pba_xcfg_t xcfg; + + /// PBAX send transaction register + pba_xsndtx_t xsndtx; + + /// PBAX send status register + pba_xsndstat_t xsndstat; + +} PbaxSendFfdc; + + +/// FFDC collected for PBAX receive errors + +typedef struct { + + /// Common FFDC + PbaCommonFfdc common; + + /// PBAX configuration register + pba_xcfg_t xcfg; + + /// PBAX receive status register + pba_xrcvstat_t xrcvstat; + + /// PBAX push base registers + pba_xshbrn_t xshbrn[PBAX_QUEUES]; + + /// PBAX push control/status registers + pba_xshcsn_t xshcsn[PBAX_QUEUES]; + +} PbaxReceiveFfdc; + + +/// A single global structure containing FFDC for all PBA functions + +typedef struct { + + /// FFDC for the generic bridge + PbaBridgeFfdc bridge; + + /// FFDC for the BCDE + BceFfdc bcde; + + /// FFDC for the BCUE + BceFfdc bcue; + + /// FFDC for PBAX send + PbaxSendFfdc pbax_send; + + /// FFDC for PBAX receive + PbaxReceiveFfdc pbax_receive; + +} PbaUnitFfdc; + +#endif // __ASSEMBLER__ + +//////////////////////////////////////////////////////////////////////////// +// BceRequest +//////////////////////////////////////////////////////////////////////////// + +#ifndef __ASSEMBLER__ + +struct BceQueue; + +/// A request to move data through the PBA BCUE or BCDE +/// +/// From a programming and control perspective the Block Copy Download Engine +/// (BCDE) and Upload Engine (BCUE) are identical - they simply move a given +/// number of 128-byte cache lines from/to system memory to/from SRAM. +/// +/// Although the PBA BCE hardware can only move a maximum of 4KB at a time +/// through the channel, the software layer allows any amount of data to be +/// moved as a single request. + +typedef struct { + + /// The generic request + AsyncRequest request; + + /// FFDC collected in the event of an error in the request + BceFfdc ffdc; + + /// Initial bridge address for read (BCDE) or write (BCUE) data. This + /// field is not modified by the drivers. + uint32_t bridge_address; + + /// Initial OCI address for read (BCUE) or write (BCDE) data. This + /// field is not modified by the drivers. + uint32_t oci_address; + + /// Number of bytes to move. This field is not modified by the drivers. + /// + /// Note that the PBA moves data in sets of 128 bytes (the PowerBus + /// cache line size). This field will always be a multiple of 128. + size_t bytes; + + /// The next bridge address for read (BCDE) or write (BCUE) data. This + /// field is modified by the drivers as each maximum 4K block is copied. + uint32_t next_bridge_address; + + /// Initial OCI address for read (BCUE) or write (BCDE) data. This + /// field is modified by the drivers as each maximum 4K block is copied. + uint32_t next_oci_address; + + /// The number of bytes remaining to be moved. + size_t remaining; + + /// The extended address, as a 64-bit PowerBus address + /// + /// Bits 23:36 of the field define bits 23:36 of the final PowerBus + /// address, subject to the final mask selection. This field is cleared by + /// the default constructor, and must be explicitly set if an extended + /// address is needed. + pba_extended_address_t extended_address; + +} BceRequest; + +int +bce_request_create(BceRequest *request, + struct BceQueue *queue, + uint32_t bridge_address, + uint32_t oci_address, + size_t bytes, + SsxInterval timeout, + AsyncRequestCallback callback, + void *arg, + int options); + +#endif /* __ASSEMBLER__ */ + + +//////////////////////////////////////////////////////////////////////////// +// BceQueue +//////////////////////////////////////////////////////////////////////////// + +// NB: This assignment ordering is assumed by static initialization code. +// These constants are used as array indices. + +#define BCE_ENGINE_BCDE 0 +#define BCE_ENGINE_BCUE 1 + +#define BCE_ENGINES 2 + +#ifndef __ASSEMBLER__ + + +/// A PBA Block Copy Engine queue +/// +/// A PBA block copy request queue consists of a generic AsyncQueue to manage +/// jobs on the engine and the PBA engine id. The BCDE and BCUE can use the +/// same driver because their control interfaces are identical. + +typedef struct BceQueue { + + /// The generic request queue + AsyncQueue queue; + + /// The engine id of the BCE engine for control register address lookup + int engine; + +} BceQueue; + + +int +bce_queue_create(BceQueue *queue, + int engine); + + +int +bce_request_schedule(BceRequest *request); + +#endif /* __ASSEMBLER__ */ + + +//////////////////////////////////////////////////////////////////////////// +// PbaxRequest +//////////////////////////////////////////////////////////////////////////// + +#ifndef __ASSEMBLER__ + +struct PbaxQueue; + +/// A request to move data through a PBAX circular queue +/// +/// The PBAX circular queues are modeled after the OCB circular queues. The +/// queues are named and documented in the hardware specifications from the +/// perspective of the PowerBus as "PUSH" queues. Here we name and document +/// the queues from the perspective of OCC firmware as "READ" queues. Note +/// that there are no PBAX "WRITE" queues. The PBAX write mechanism handles +/// only a single datum at a time and has no interrupt. PBAX writes are +/// handled by the pbax_send() and _pbax_send() APIs. +/// +/// The PBAX queues support data buffers of from 8 to 256 bytes with an 8-byte +/// granularity. The PBAX hardware requires that the data buffers be aligned +/// to a power-of-2 boundary greater than or equal to the buffer size. +/// The async drivers allow specification of any multiple of 8 bytes to read +/// and handle all of the queue and split-request management. +/// +/// Note : As long as the PbaxRequest is idle, the application is free to +/// directly change the \a data and \a bytes fields to read/write different +/// numbers of bytes to/from different locations the next time the request is +/// scheduled. +/// +/// The PBAX queues support both 'lazy' and 'aggressive' interrupt protocols. +/// The aggressive protocols generate interrupts whenever read data is +/// available. The lazy protocols require a full read buffer to trigger an +/// interrupt. A lazy read protocol with a buffer size > 1 demands that +/// communcations always consist of a known number of doublewords equal to the +/// buffer size. For free-form communications an aggressive read protocol must +/// be used. + +typedef struct { + + /// The generic request + AsyncRequest request; + + /// Initial pointer to the data area to hold read data. + /// + /// This field is not modified by the drivers. The application may modify + /// this field any time the PbaxRequest is idle. + uint64_t *data; + + /// Number of bytes to move, which must be a multiple of 8. + /// + /// This field is not modified by the drivers. The application may modify + /// this field any time the PbaxRequest is idle. + size_t bytes; + + /// Pointer to where to put the next read data. + /// + /// The application should never modify this field. + void* current; + + /// Number of bytes remaining to be moved. + /// + /// The application should never modify this field. + size_t remaining; + +} PbaxRequest; + + +int +pbax_request_create(PbaxRequest *request, + struct PbaxQueue *queue, + uint64_t *data, + size_t bytes, + SsxInterval timeout, + AsyncRequestCallback callback, + void *arg, + int options); + + +int +pbax_request_schedule(PbaxRequest *request); + +#endif /* __ASSEMBLER__ */ + + +//////////////////////////////////////////////////////////////////////////// +// PbaxQueue +//////////////////////////////////////////////////////////////////////////// + +// NB: This assignment ordering is assumed by static initialization code in +// pgp_async.c - these constants are used as array indices. + +#define PBAX_ENGINE_PUSH0 0 +#define PBAX_ENGINE_PUSH1 1 + +#define PBAX_ENGINES 2 + +#ifndef __ASSEMBLER__ + +extern const SsxAddress pba_xshcsn[]; +extern const SsxAddress pba_xshbrn[]; +extern const SsxAddress pba_xshincn[]; + + +/// A PBAX Circular buffer queue +/// +/// A PBAX circular buffer queue consists of a generic AsyncQueue to manage +/// jobs on the engine, a pointer to the data area and the PBAX engine id. + +typedef struct PbaxQueue { + + /// The generic request queue + AsyncQueue queue; + + /// The base of the circular queue data area + /// + /// This data area must satisfy stringent alignment constraints; See the + /// documentation for PbaxRequest. + uint64_t *cq_base; + + /// The number of 8-byte entries in the queue. + /// + /// This is included here to simplify APIs; The length is also encoded in + /// the PBAXSHCSn register for the queue. + size_t cq_entries; + + /// The interrupt protocol implemented by the queue. + /// + /// This will either be PBAX_INTERRUPT_PROTOCOL_LAZY or + /// PBAX_INTERRUPT_PROTOCOL_AGGRESSIVE. + int protocol; + + /// The engine id for lookup of OCI control register addresses. + int engine; + + /// The IRQ associated with normal completion on the engine + /// + /// \todo Due to header reference ordering we can't define this as SsxIrqId + uint8_t irq; + +} PbaxQueue; + + +int +pbax_queue_create(PbaxQueue *queue, + int engine, + uint64_t *cq_base, + size_t cq_entries, + int protocol); + +int +pbax_queue_disable(PbaxQueue *queue); + +int +pbax_queue_enable(PbaxQueue *queue); + +int +pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read); + +#endif /* __ASSEMBLER__ */ + + +//////////////////////////////////////////////////////////////////////////// +// OcbRequest +//////////////////////////////////////////////////////////////////////////// + +#ifndef __ASSEMBLER__ + +/// OCB FFDC +/// +/// This structure is used to store FFDC in two cases. 1) When an error can be +/// reasonably attributed to an OCB channel under the control of OCC, and 2) +/// general errors signalled by the OCB direct bridge. Due to the myriad ways +/// that OCB channels can be used the FFDC for OCB direct bridge errors is +/// stored globally rather than with particular requests or queues. +/// +/// The OcbFfdc includes the PLB arbiter PEARL and PESR register state. +/// This state is only collected if the error status indicates an OCI timeout +/// for this channel. +/// +/// Any error reasonably attributable to a channel will capture the FFDC and +/// then disable the channel since any further communication through the +/// channel must be considered compromised. + +typedef struct { + + /// FFDC from the OCI (PLB) arbiter + OciFfdc oci_ffdc; + + /// A copy of the OCB OCC_LFIR register at the time of the error + ocb_occlfir_t fir; + + /// A copy of the OCB Control/Status register for the channel at the time + /// of the error. + /// + /// This field will be set to 0 for generic OCB bridge errors + ocb_ocbcsrn_t csr; + + /// A copy of the OCB Stream Push Base [n] Register at the time of the + /// failure + /// + /// This field will be set to 0 for generic OCB bridge errors + ocb_ocbshbrn_t shbr; + + /// A copy of the OCB Stream Push Control/Status [n] Register at the time + /// of the failure + /// + /// This field will be set to 0 for generic OCB bridge errors + ocb_ocbshcsn_t shcs; + + /// A copy of the OCB Stream Pull Base [n] Register at the time of the + /// failure + /// + /// This field will be set to 0 for generic OCB bridge errors + ocb_ocbslbrn_t slbr; + + /// A copy of the OCB Stream Pull Control/Status [n] Register at the time + /// of the failure + /// + /// This field will be set to 0 for generic OCB bridge errors + ocb_ocbslcsn_t slcs; + + /// Is this record valid (does it contain captured error information)? + int error; + +} OcbFfdc; + + +/// OCB Unit FFDC +/// +/// Contains FFDC structures for each channel and the direct bridge + +typedef struct { + + OcbFfdc channel[OCB_INDIRECT_CHANNELS]; + OcbFfdc bridge; + +} OcbUnitFfdc; + + +/// Global FFDC for OCB + +extern OcbUnitFfdc G_ocb_ffdc; + + +struct OcbQueue; + +/// A request to move data through an OCB circular queue +/// +/// The OCB circular queues are named and documented in the hardware specs +/// from the perspective of the PIB - "PUSH" and "PULL" queues. Here we name +/// and document the queues from the perspective of OCC firmware - "READ" and +/// "WRITE" queues. The request is generic and becomes either a read or write +/// request simply by which queue it is scheduled on. +/// +/// The circular queues only support 8-byte granularity, require that the data +/// areas be 8- or 32-byte aligned, and only support up to 256 byte +/// queues. However the async drivers allow specification of any multiple of 8 +/// bytes to read or write, and handle all of the queue and split-request +/// management. +/// +/// Note : As long as the OcbRequest is idle, the application is free to +/// directly change the \a data and \a bytes fields to read/write different +/// numbers of bytes to/from different locations the next time the request is +/// scheduled. +/// +/// OCB requests always complete in an interrupt context. The OCB queues +/// support both 'lazy' and 'aggressive' interrupt protocols. The aggressive +/// protocols generate interrupts whenever read data is available or write +/// space is available. The lazy protocols require a full read buffer or +/// empty write buffer to trigger an interrupt. A lazy read protocol with a +/// buffer size > 1 demands that communcations always consist of a known +/// number of doublewords. For free-form communications an aggressive read +/// protocol must be used. On average, an aggressive write protocol will +/// shorten blocking periods of writers, and can guarantee that data is in the +/// queue whenever data is avilable. Lazy write protocols will be preferred +/// when reducing interrupt overhead is more important than reducing blocking +/// time. +/// +/// Completion of write requests does not guarantee that the communication +/// partner has received the data, but simply that the data has been queued +/// for reception and the caller may reuse/refill the data buffer if required. + +typedef struct { + + /// The generic request + AsyncRequest request; + + /// Initial pointer to the data to be moved for write data, or the + /// data area to hold read data. This field is not modified by the drivers. + uint64_t *data; + + /// Number of bytes to move. This field is not modified by the drivers. + size_t bytes; + + /// Pointer to data yet to be moved for write, or where to put the next + /// read data. + uint64_t* current; + + /// Number of bytes remaining to be moved. + size_t remaining; + +} OcbRequest; + + +int +ocb_request_create(OcbRequest *request, + struct OcbQueue *queue, + uint64_t *data, + size_t bytes, + SsxInterval timeout, + AsyncRequestCallback callback, + void *arg, + int options); + + +int +ocb_request_schedule(OcbRequest *request); + +#endif /* __ASSEMBLER__ */ + + +//////////////////////////////////////////////////////////////////////////// +// OcbQueue +//////////////////////////////////////////////////////////////////////////// + +// NB: This assignment ordering is assumed by static initialization code in +// pgp_async.c - these constants are used as array indices. The code also +// assumes this ordering for the access of G_ocb_ocbsesn[], and for +// determining whether the engine is a PUSH or PULL queue. +// Note: push/pull queues for channel 3 have been deleted + +#define OCB_ENGINE_PUSH0 0 +#define OCB_ENGINE_PULL0 1 +#define OCB_ENGINE_PUSH1 2 +#define OCB_ENGINE_PULL1 3 +#define OCB_ENGINE_PUSH2 4 +#define OCB_ENGINE_PULL2 5 + +#define OCB_ENGINES 6 + +#ifndef __ASSEMBLER__ + +/// An OCB Circular buffer queue +/// +/// A OCB circular buffer queue consists of a generic AsyncQueue to manage +/// jobs on the engine, a pointer to the data area and the OCB engine id. + +typedef struct OcbQueue { + + /// The generic request queue + AsyncQueue queue; + + /// The base of the circular queue data area - must be 8-byte aligned + uint64_t *cq_base; + + /// The length of the queue in terms of the number of 8-byte entries in + /// the queue. + /// + /// This is for informational purposes only. The length is also encoded + /// in the OCBSxCSn register for the queue. + size_t cq_length; + + /// The engine id for lookup of OCI control register addresses. + int engine; + + /// The IRQ associated with normal completion on the engine + /// + /// \todo Due to header reference ordering we can't define this as SsxIrqId + uint8_t irq; + +} OcbQueue; + + +int +ocb_queue_create(OcbQueue *queue, + int engine, + uint64_t *cq_base, + size_t cq_length, + int protocol); + +#endif /* __ASSEMBLER__ */ + + +//////////////////////////////////////////////////////////////////////////// +// Miscellaneous/Initialization +//////////////////////////////////////////////////////////////////////////// + +// Error codes + +#define ASYNC_INVALID_OBJECT_REQUEST 0x00279600 +#define ASYNC_INVALID_OBJECT_SCHEDULE 0x00279601 +#define ASYNC_INVALID_OBJECT_OCB_REQUEST 0x00279602 +#define ASYNC_INVALID_OBJECT_OCB_QUEUE 0x00279603 +#define ASYNC_INVALID_OBJECT_PBAX_REQUEST 0x00279604 +#define ASYNC_INVALID_OBJECT_PBAX_DISABLE 0x00279605 +#define ASYNC_INVALID_OBJECT_PBAX_QUEUE 0x00279606 +#define ASYNC_INVALID_OBJECT_BCE_REQUEST 0x00279607 +#define ASYNC_INVALID_OBJECT_BCE_QUEUE 0x00279608 +#define ASYNC_INVALID_OBJECT_PORE_REQUEST 0x00279609 +#define ASYNC_INVALID_OBJECT_PORE_QUEUE 0x0027960a +#define ASYNC_INVALID_OBJECT_PTS_REQUEST 0x0027960b +#define ASYNC_INVALID_OBJECT_PTS_THREAD 0x0027960c +#define ASYNC_INVALID_OBJECT_PTS_QUEUE 0x0027960d +#define ASYNC_INVALID_OBJECT_PTS_START 0x0027960e +#define ASYNC_INVALID_OBJECT_PTS_SCHEDULE 0x0027960f +#define ASYNC_INVALID_ARGUMENT 0x00279610 +#define ASYNC_INVALID_ARGUMENT_OCB_READ 0x00279611 +#define ASYNC_INVALID_ARGUMENT_OCB_WRITE 0x00279612 +#define ASYNC_INVALID_ARGUMENT_OCB_QUEUE 0x00279613 +#define ASYNC_INVALID_ARGUMENT_OCB_QUEUE2 0x00279614 +#define ASYNC_INVALID_ARGUMENT_OCB_REQUEST 0x00279615 +#define ASYNC_INVALID_ARGUMENT_OCB_SCHEDULE 0x00279616 +#define ASYNC_INVALID_ARGUMENT_BCE_SCHEDULE 0x00279617 +#define ASYNC_INVALID_ARGUMENT_PBAX_READ 0x00279618 +#define ASYNC_INVALID_ARGUMENT_PBAX_REQUEST 0x00279619 +#define ASYNC_INVALID_ARGUMENT_PBAX_SCHEDULE 0x0027961a +#define ASYNC_INVALID_ARGUMENT_PBAX_QUEUE 0x0027961b +#define ASYNC_INVALID_ARGUMENT_PORE_REQUEST 0x0027961c +#define ASYNC_INVALID_ARGUMENT_PTS_THREAD 0x0027961d +#define ASYNC_INVALID_ARGUMENT_PTS_REQUEST 0x0027961e +#define ASYNC_INVALID_ENGINE_OCB 0x0027961f +#define ASYNC_INVALID_ENGINE_PBAX 0x00279620 +#define ASYNC_INVALID_ENGINE_BCE 0x00279621 +#define ASYNC_INVALID_ENGINE_PORE 0x00279622 +#define ASYNC_INVALID_ENGINE_PTS 0x00279623 +#define ASYNC_INVALID_OPTIONS 0x00279624 +#define ASYNC_INVALID_ASSIGNMENT 0x00279625 +#define ASYNC_CALLBACK_PROTOCOL_UNSPECIFIED 0x00279626 +#define ASYNC_REQUEST_NOT_IDLE 0x00279627 +#define ASYNC_REQUEST_NOT_IDLE_PTS 0x00279628 +#define ASYNC_REQUEST_COMPLETE 0x00279629 +#define ASYNC_INVALID_TIMESTAMPS 0x0027962a +#define ASYNC_OCB_ERROR_READ_OLD 0x0027962b +#define ASYNC_OCB_ERROR_READ_NEW 0x0027962c +#define ASYNC_OCB_ERROR_WRITE_OLD 0x0027962d +#define ASYNC_OCB_ERROR_WRITE_NEW 0x0027962e +#define ASYNC_PBAX_ERROR_OLD 0x0027962f +#define ASYNC_PBAX_ERROR_NEW 0x00279630 +#define ASYNC_REQUEST_NOT_COMPLETE 0x00279631 +#define ASYNC_REQUEST_NOT_COMPLETE_PTS 0x00279632 + +// Panic codes + +#define ASYNC_PORE_FIXED_INVARIANT 0x00279633 +#define ASYNC_PHANTOM_INTERRUPT 0x00279634 +#define ASYNC_PHANTOM_INTERRUPT_OCB 0x00279635 +#define ASYNC_PHANTOM_INTERRUPT_BCE 0x00279636 +#define ASYNC_PHANTOM_INTERRUPT_PBAX 0x00279637 +#define ASYNC_SCOM_ERROR 0x00279638 +#define ASYNC_TIMEOUT_BUG 0x00279639 +#define ASYNC_INVALID_STATE 0x0027963a +#define ASYNC_PHANTOM_ERROR 0x0027963b +#define ASYNC_BUG_PORE_AT_CREATE 0x0027963c +#define ASYNC_BUG_PTS_AT_CREATE 0x0027963d +#define ASYNC_BUG_PTS_AT_RUN 0x0027963e + +//////////////////////////////////////////////////////////////////////////// +// Global Data and Constants +//////////////////////////////////////////////////////////////////////////// + +#ifndef __ASSEMBLER__ + +// PORE Queues + +extern PoreQueue G_pore_gpe0_queue; +extern PoreQueue G_pore_gpe1_queue; +extern PoreQueue G_pore_slw_queue; + +/// Define a PORE branch table. All error slots are always defined, but space +/// can be saved if not all of the entry points are required. +#define PORE_TABLE(var, slots) PoreBraia var[PORE_ERROR_SLOTS + (slots)] + + +// PTS Queues +// +// These queues are only defined if CONFIGURE_PTS is non-zero. CONFIGURE_PTS +// is 0 by default. + +#ifndef CONFIGURE_PTS +#define CONFIGURE_PTS 0 +#endif + +#if CONFIGURE_PTS +#include "pgp_async_pts.h" +extern PtsQueue G_pts_gpe0_queue; +extern PtsQueue G_pts_gpe1_queue; +#endif + + +// OCB Queues and FFDC + +// OCB circular queue naming is confusing, because PUSH/PULL are defined from +// the perspective of the PIB. This driver uses the terms read/write +// respectively and represents the hardware from the perspective of code +// running on OCC. + +// OCB read/write queue lengths are defined in terms of doublewords, and must +// be in a small defined range. Two meaningful interrupt protocols are +// possible for a queue: 'LAZY' allows read/write queues to fill/empty +// respectively before an interrupt is signalled. 'AGRESSIVE' signals an +// interrupt whenever there is data to be read or a free slot to put write +// data. + +// In a production system the lengths and protocols will likely vary based on +// the particular application and the characteristics of the communication +// partner. By default the queues take on their maximum lengths. Read queues +// use the aggressive protocol which allows free-form communication. Write +// queues use lazy protoclols which reduces interrupt overhead. Different +// effective lengths and the interrupt protocols can be changed later if +// desired - assuming the queues are idle when the changes are made. + +#define OCB_PUSH_PULL_LENGTH_MIN 1 +#define OCB_PUSH_PULL_LENGTH_MAX 32 + +#define OCB_INTERRUPT_PROTOCOL_LAZY 0 +#define OCB_INTERRUPT_PROTOCOL_AGGRESSIVE 1 + +#define OCB_READ0_LENGTH OCB_PUSH_PULL_LENGTH_MAX +#define OCB_READ1_LENGTH OCB_PUSH_PULL_LENGTH_MAX +#define OCB_READ2_LENGTH OCB_PUSH_PULL_LENGTH_MAX + +#define OCB_WRITE0_LENGTH OCB_PUSH_PULL_LENGTH_MAX +#define OCB_WRITE1_LENGTH OCB_PUSH_PULL_LENGTH_MAX +#define OCB_WRITE2_LENGTH OCB_PUSH_PULL_LENGTH_MAX + +#define OCB_READ0_PROTOCOL OCB_INTERRUPT_PROTOCOL_AGGRESSIVE +#define OCB_READ1_PROTOCOL OCB_INTERRUPT_PROTOCOL_AGGRESSIVE +#define OCB_READ2_PROTOCOL OCB_INTERRUPT_PROTOCOL_AGGRESSIVE + +#define OCB_WRITE0_PROTOCOL OCB_INTERRUPT_PROTOCOL_LAZY +#define OCB_WRITE1_PROTOCOL OCB_INTERRUPT_PROTOCOL_LAZY +#define OCB_WRITE2_PROTOCOL OCB_INTERRUPT_PROTOCOL_LAZY + +extern OcbUnitFfdc G_ocb_ffdc; + +extern OcbQueue G_ocb_read_queue[]; +extern OcbQueue G_ocb_write_queue[]; + +extern uint64_t G_ocb_read0_buffer[]; +extern uint64_t G_ocb_read1_buffer[]; +extern uint64_t G_ocb_read2_buffer[]; + +extern uint64_t G_ocb_write0_buffer[]; +extern uint64_t G_ocb_write1_buffer[]; +extern uint64_t G_ocb_write2_buffer[]; + + +// PBA Queues + +/// Block Copy Upload (OCI -> PowerBus) Engine job queue; +extern BceQueue G_pba_bcue_queue; + +/// Block Copy Download Engine (PowerBus -> OCI) job queue; +extern BceQueue G_pba_bcde_queue; + + +// PBAX Queues + +// PBAX circular queue naming is confusing, because "PUSH" is defined from the +// perspective of the PowerBus. This driver uses the term "READ" and +// represents the hardware from the perspective of code running on OCC. + +// PBAX read queue lengths are defined in terms of 8-byte doublewords, and +// must be in a small defined range. Two meaningful interrupt protocols are +// possible for a queue: 'LAZY' allows read queues to fill before an interrupt +// is signalled. 'AGRESSIVE' signals an interrupt whenever there is data to +// be read. + +// In a production system the lengths and protocols will likely vary based on +// the particular application and the characteristics of the communication +// partner. By default the queues take on their maximum lengths. Read queues +// use the aggressive protocol which allows free-form communication. Different +// effective lengths and the interrupt protocols can be changed later if +// desired - assuming the queues are idle when the changes are made. + +#define PBAX_PUSH_LENGTH_MIN 1 +#define PBAX_PUSH_LENGTH_MAX 32 + +#define PBAX_INTERRUPT_PROTOCOL_LAZY 0 +#define PBAX_INTERRUPT_PROTOCOL_AGGRESSIVE 1 + +#define PBAX_READ0_LENGTH PBAX_PUSH_LENGTH_MAX +#define PBAX_READ1_LENGTH PBAX_PUSH_LENGTH_MAX + +#define PBAX_READ0_PROTOCOL PBAX_INTERRUPT_PROTOCOL_AGGRESSIVE +#define PBAX_READ1_PROTOCOL PBAX_INTERRUPT_PROTOCOL_AGGRESSIVE + +/// Job queues for the PBAX circular buffers +extern PbaxQueue G_pbax_read_queue[]; + + +// PBAX read buffers must be cache-line aligned since they are invalidated, +// and furthermore must be aligned to the next higher power-of-two of their +// lengths. Some minor efficiencies could probably be obtained by a policy +// that buffers be held in non-cacheable storage (and subsequent modifications +// to the device driver code). +// +// Due to linker restrictions, only initialized data areas can be aligned. + + +#define _PBAX_ALIGN_(length) \ + (((length) <= 4) ? 32 : \ + (((length) <= 8) ? 64 : \ + (((length) <= 16) ? 128 : 256))) + +#define PBAX_CQ_READ_BUFFER(buffer, length) \ + uint64_t buffer[length] \ + __attribute__ ((aligned (_PBAX_ALIGN_(length)))) = {0} + + +extern uint64_t G_pbax_read0_buffer[]; +extern uint64_t G_pbax_read1_buffer[]; + + +// Initialization APIs + +void +async_pore_initialize(PoreQueue *queue, int engine); + +void +async_bce_initialize(BceQueue *queue, int engine, SsxIrqId irq); + + +void +async_ocb_initialize(OcbQueue *queue, int engine, + uint64_t *buffer, size_t length, int protocol); + + +void +async_pbax_initialize(PbaxQueue *queue, int engine, SsxIrqId irq, + uint64_t *buffer, size_t length, int protocol); + + +void +async_initialize(); + +#endif /* __ASSEMBLER__ */ + +#endif /* __PGP_ASYNC_H__ */ diff --git a/src/ssx/pgp/pgp_async_ocb.c b/src/ssx/pgp/pgp_async_ocb.c new file mode 100755 index 0000000..b9ef4b8 --- /dev/null +++ b/src/ssx/pgp/pgp_async_ocb.c @@ -0,0 +1,953 @@ +// $Id: pgp_async_ocb.c,v 1.2 2014/02/03 01:30:34 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_async_ocb.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_async_ocb.c +/// \brief Async driver code for OCB + +#include "ssx.h" + + +//////////////////////////////////////////////////////////////////////////// +// Global Data +//////////////////////////////////////////////////////////////////////////// + +OcbUnitFfdc G_ocb_ffdc = {{{{{0}}}}}; + +OcbQueue G_ocb_read_queue[OCB_INDIRECT_CHANNELS]; +OcbQueue G_ocb_write_queue[OCB_INDIRECT_CHANNELS]; + + +#if OCB_READ0_LENGTH % CACHE_LINE_SIZE +#error "OCB read buffer 0 alignment error" +#endif +#if OCB_READ1_LENGTH % CACHE_LINE_SIZE +#error "OCB read buffer 1 alignment error" +#endif +#if OCB_READ2_LENGTH % CACHE_LINE_SIZE +#error "OCB read buffer 2 alignment error" +#endif +#if OCB_READ3_LENGTH % CACHE_LINE_SIZE +#error "OCB read buffer 3 alignment error" +#endif + +// OCB circular queue write buffers must be 8-byte aligned per hardware +// restrictions, whereas read buffers are cache-line aligned and must be an +// even multiple of the cache line size since they must be invalidated. Some +// minor efficiencies could probably be obtained by a policy that CQ buffers +// be held in non-cacheable storage (and subsequent modifications to the +// device driver code). +// +// Due to linker restrictions, only initialized data areas can be aligned. + +#define OCB_CQ_WRITE_BUFFER(buffer, length) \ + uint64_t buffer[length] __attribute__ ((aligned (8))) = {0} + +#define OCB_CQ_READ_BUFFER(buffer, length) \ + uint64_t buffer[length] __attribute__ ((aligned (CACHE_LINE_SIZE))) = {0} + + +OCB_CQ_READ_BUFFER(G_ocb_read0_buffer, OCB_READ0_LENGTH); +OCB_CQ_READ_BUFFER(G_ocb_read1_buffer, OCB_READ1_LENGTH); +OCB_CQ_READ_BUFFER(G_ocb_read2_buffer, OCB_READ2_LENGTH); + +OCB_CQ_WRITE_BUFFER(G_ocb_write0_buffer, OCB_WRITE0_LENGTH); +OCB_CQ_WRITE_BUFFER(G_ocb_write1_buffer, OCB_WRITE1_LENGTH); +OCB_CQ_WRITE_BUFFER(G_ocb_write2_buffer, OCB_WRITE2_LENGTH); + + +//////////////////////////////////////////////////////////////////////////// +// Local Data +//////////////////////////////////////////////////////////////////////////// + +/// \todo These addresses could/should simply be stored with the queue objects +/// to avoid these static data declarations. + +/// OCB Stream Push/Pull Control/Status Register addresses + +static const SsxAddress G_ocb_ocbsxcsn[OCB_ENGINES] = + {OCB_OCBSHCS0, OCB_OCBSLCS0, + OCB_OCBSHCS1, OCB_OCBSLCS1, + OCB_OCBSHCS2, OCB_OCBSLCS2}; + +/// OCB Stream Push/Pull Base Register addresses + +static const SsxAddress G_ocb_ocbsxbrn[OCB_ENGINES] = + {OCB_OCBSHBR0, OCB_OCBSLBR0, + OCB_OCBSHBR1, OCB_OCBSLBR1, + OCB_OCBSHBR2, OCB_OCBSLBR2}; + + +/// OCB Stream Push/Pull Increment Register addresses + +static const SsxAddress G_ocb_ocbsxin[OCB_ENGINES] = + {OCB_OCBSHI0, OCB_OCBSLI0, + OCB_OCBSHI1, OCB_OCBSLI1, + OCB_OCBSHI2, OCB_OCBSLI2}; + + +/// OCB Stream Error Status; There is only one register per OCB channel + +const SsxAddress G_ocb_ocbsesn[OCB_ENGINES / 2] = + {OCB_OCBSES0, OCB_OCBSES1, OCB_OCBSES2}; + + +//////////////////////////////////////////////////////////////////////////// +// OcbRequest +//////////////////////////////////////////////////////////////////////////// + +// Collect FFDC for an OCB channel +// +// This is an internal API, called either due to an OCB error interrupt or a +// read/write error detected during the operation. See the comments for +// OcbFfdc for a description of why this particular set of data is collected. +// The special channel number -1 is used to denote the direct bridge. +// +// OCB FFDC collection procedure: +// +// - Collect the OCBSCR<n> for indirect channels +// +// - Collect PUSH/PULL queue setup for indirect channels and disable the queues. +// +// - Collect the OCB FIR +// +// - Collect FFDC from the PLB (OCI) arbiter +// +// FFDC is only collected for the first error, until the error flag is reset. + +static void +ocb_ffdc(int channel) +{ + OcbFfdc* ffdc; + + if (channel < 0) { + ffdc = &(G_ocb_ffdc.bridge); + } else { + ffdc = &(G_ocb_ffdc.channel[channel]); + } + + if (ffdc->error == 0) { + + if (channel < 0) { + + memset(ffdc, 0, sizeof(OcbFfdc)); + + } else { + + getscom(OCB_OCBCSRN(channel), &(ffdc->csr.value)); + + ffdc->shbr.value = in32(OCB_OCBSHBRN(channel)); + ffdc->shcs.value = in32(OCB_OCBSHCSN(channel)); + ffdc->slbr.value = in32(OCB_OCBSLBRN(channel)); + ffdc->slcs.value = in32(OCB_OCBSLCSN(channel)); + + out32(OCB_OCBSHCSN(channel), + ffdc->shcs.value & ~OCB_OCBSHCSN_PUSH_ENABLE); + out32(OCB_OCBSLCSN(channel), + ffdc->slcs.value & ~OCB_OCBSLCSN_PULL_ENABLE); + + } + + getscom(OCB_OCCLFIR, &(ffdc->fir.value)); + + oci_ffdc(&(ffdc->oci_ffdc), OCI_MASTER_ID_OCB); + + ffdc->error = 1; + } +} + + +/// Non-blocking read from an OCB PUSH (read) queue +/// +/// \param queue The target OcbQueue +/// +/// \param buf The caller's data buffer to receive the read data +/// +/// \param bytes The maximum number of bytes to read. This value must be an +/// even multiple of 8, as this API always reads multiples of 8 bytes. +/// +/// \param read The number of bytes actually copied from the device buffer to +/// the caller's buffer. This may be returned as any value from 0 to \a +/// bytes in multiples of 8 bytes. +/// +/// ocb_read() implements a non-blocking copy of data from an OCB read (PUSH) +/// queue data area to the caller's data area, with the side effect of +/// advancing the hardware queue pointers. ocb_read() does not implement +/// locking, critical sections or any other type of synchronization for access +/// to the OCB queue data - that is the responsibility of the caller. +/// +/// ocb_read() may return an error code. This may indicate a preexisting +/// error in the queue, or may be an error resulting from the current read. +/// In either event any read data should be considered corrupted. +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_ARGUMENT_OCB_READ The number of \a bytes is not +/// an even multiple of 8. +/// +/// \retval -ASYNC_OCB_ERROR_READ_OLD or -ASYNC_OCB_ERROR_READ_NEW This code +/// indicates an error associated with the OCB channel represented by the queue. + +int +ocb_read(OcbQueue *queue, void* buf, size_t bytes, size_t* read) +{ + ocb_ocbshcsn_t csr; + ocb_ocbsesn_t ses; + unsigned qlen, read_ptr, write_ptr, to_read; + uint64_t *pcq, *pbuf; + int rc; + + do { + + rc = 0; + *read = 0; + + // If pre-existing errors exist then immediately abort the read. + + if (G_ocb_ffdc.channel[queue->engine / 2].error) { + rc = -ASYNC_OCB_ERROR_READ_OLD; + break; + } + + if (bytes % 8) { + rc = -ASYNC_INVALID_ARGUMENT_OCB_READ; + break; + } + + // Determine the number of doubleword entries remaining to be read in + // the queue. The driver does not keep state, but instead reinterprets + // the control/status register each time ocb_read() is called. + + // This may be confusing - remember that 'push' and 'pull' are from + // the PIB perspective - here we use 'read' and 'write' from OCC's + // perspective. + + csr.value = in32(G_ocb_ocbsxcsn[queue->engine]); + + qlen = csr.fields.push_length + 1; + read_ptr = csr.fields.push_read_ptr; + + if (csr.fields.push_empty) { + break; + + } else if (csr.fields.push_full) { + to_read = qlen; + + } else { + write_ptr = csr.fields.push_write_ptr; + if (read_ptr > write_ptr) { + to_read = qlen - (read_ptr - write_ptr); + } else { + to_read = write_ptr - read_ptr; + } + } + + // Copy the data from the CQ memory area to the user's buffer. For + // simplicty of dealing with cache management each doubleword invokes + // a line invalidate before refetching the fresh data from + // memory. Alignment requirements enforced on the data buffer + // guarantee the buffers are cache-line aligned and each doubleword is + // fully contained in a single D-cache line. + // + // Here the code models the evolution of the read_ptr as each datum is + // copied from the queue. + + pbuf = (uint64_t*)buf; + while (bytes && to_read--) { + + read_ptr++; + if (read_ptr == qlen) { + read_ptr = 0; + } + pcq = queue->cq_base + read_ptr; + + dcache_invalidate_line(pcq); + *pbuf++ = *pcq; + out32(G_ocb_ocbsxin[queue->engine], 0); + + bytes -= 8; + *read += 8; + } + } while (0); + + // Check for underflow errors. If found, collect FFDC. + + ses.value = in32(G_ocb_ocbsesn[queue->engine / 2]); + if (ses.fields.push_read_underflow) { + ocb_ffdc(queue->engine / 2); + rc = -ASYNC_OCB_ERROR_READ_NEW; + } + + return rc; +} + + +/// Non-blocking write to an OCB PULL (write) queue +/// +/// \param queue The target OcbQueue +/// +/// \param buf The caller's data buffer containing the write data +/// +/// \param bytes The maximum number of bytes to write. This value must be an +/// even multiple of 8, as this API always writes multiples of 8 bytes. +/// +/// \param written The number of bytes actually copied from the caller's buffer to +/// the device buffer. This may be returned as any value from 0 to \a +/// bytes in multiples of 8 bytes. +/// +/// ocb_write() implements a non-blocking copy of data to an OCB write (PULL) +/// queue, with the side effect of advancing the hardware queue pointers. +/// ocb_write() does not implement locking, critical sections or any other +/// type of synchronization for access to the OCB queue data - that is the +/// responsibility of the caller. +/// +/// ocb_write() may return an error code. This may indicate a preexisting +/// error in the queue, or may be an error resulting from the current write. +/// In either event any write data should be considered corrupted/nondelivered. +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_ARGUMENT_OCB_WRITE The number of \a bytes is not +/// an even multiple of 8. +/// +/// \retval -ASYNC_OCB_ERROR_WRITE_OLD or -ASYNC_OCB_ERROR_WRITE_NEW This code +/// indicates an error associated with the OCB channel represented by the queue. + +int +ocb_write(OcbQueue *queue, void* buf, size_t bytes, size_t* written) +{ + ocb_ocbslcsn_t csr; + ocb_ocbsesn_t ses; + unsigned qlen, read_ptr, write_ptr, free; + uint64_t *pcq, *pbuf; + int rc; + + do { + + rc = 0; + *written = 0; + + // Pre-existing errors immediately abort the read. + + if (G_ocb_ffdc.channel[queue->engine / 2].error) { + rc = -ASYNC_OCB_ERROR_WRITE_OLD; + break; + } + + if (bytes % 8) { + rc = -ASYNC_INVALID_ARGUMENT_OCB_WRITE; + break; + } + + // Determine the number of free doubleword entries remaining in the + // queue. The driver does not keep state, but instead reinterprets the + // control/status register each time the write method is called. + + // This is confusing - remember that 'push' and 'pull' are from the PIB + // perspective - here we use 'read' and 'write' from OCC's perspective. + + csr.value = in32(G_ocb_ocbsxcsn[queue->engine]); + + qlen = csr.fields.pull_length + 1; + write_ptr = csr.fields.pull_write_ptr; + + if (csr.fields.pull_full) { + break; + } + + if (csr.fields.pull_empty) { + free = qlen; + } else { + read_ptr = csr.fields.pull_read_ptr; + if (write_ptr > read_ptr) { + free = qlen - (write_ptr - read_ptr); + } else { + free = read_ptr - write_ptr; + } + } + + // Copy the data into the CQ memory area. For simplicty of dealing + // with cache management each doubleword invokes a line flush before + // incrementing the hardware pointer. Alignment requirements enforced + // on the data buffer guarantee each doubleword is fully contained in + // a single D-cache line. + // + // Here the code models the evolution of the write_ptr as each datum is + // copied into the queue. + + pbuf = (uint64_t*)buf; + while (bytes && free--) { + + write_ptr++; + if (write_ptr == qlen) { + write_ptr = 0; + } + pcq = queue->cq_base + write_ptr; + + *pcq = *pbuf++; + dcache_flush_line(pcq); + in32(G_ocb_ocbsxin[queue->engine]); + + bytes -= 8; + *written += 8; + } + } while (0); + + // Check for overflow. If found, collect FFDC. + + ses.value = in32(G_ocb_ocbsesn[queue->engine / 2]); + if (ses.fields.pull_write_overflow) { + ocb_ffdc(queue->engine / 2); + rc = -ASYNC_OCB_ERROR_WRITE_NEW; + } + + return rc; +} + + +// This is the internal 'run method' for reading through an OCB circular +// queue. The run method simply enables the IRQ. The interrupt handler reads +// data from the queue and leaves the interrupt enabled until the read is +// satisfied. + +static int +ocb_read_method(AsyncRequest *async_request) +{ + OcbRequest *request = (OcbRequest*)async_request; + OcbQueue *queue = (OcbQueue*)(async_request->queue); + int rc; + + if (request->bytes == 0) { + rc = -ASYNC_REQUEST_COMPLETE; + } else { + ssx_irq_enable(queue->irq); + rc = 0; + } + return rc; +} + + +// This is the internal 'run method' for writing through an OCB circular +// queue. The run method simply enables the IRQ. The interrupt handler writes +// data from the queue and leaves the interrupt enabled until the write is +// satisfied. + +static int +ocb_write_method(AsyncRequest *async_request) +{ + OcbRequest *request = (OcbRequest *)async_request; + OcbQueue *queue = (OcbQueue*)(async_request->queue); + int rc; + + if (request->bytes == 0) { + rc = -ASYNC_REQUEST_COMPLETE; + } else { + ssx_irq_enable(queue->irq); + rc = 0; + } + return rc; +} + + +// The async error method for OCB +// +// Collect FFDC. The return of -1 will disable the channel associated with +// the request. + +static int +ocb_async_error_method(AsyncRequest *request) +{ + OcbQueue *queue = (OcbQueue*)(request->queue); + ocb_ffdc(queue->engine / 2); + return -1; +} + + +/// Create a request for an OCB circular queue +/// +/// \param request An uninitialized or otherwise idle OcbRequest. +/// +/// \param queue An async queue for an OCB circular buffer. The queue \a +/// engine determines whether this is a read or write request. +/// +/// \param data A pointer to the data to be moved (for write) or where the +/// data should be placed (for read). +/// +/// \param bytes The number of bytes of data to move. The OCB +/// circular buffers always move multiples of 8 bytes, and the number of bytes +/// must be a multiple of 8. Higher-level abstractions will have to take care +/// of cases where the numbers of bytes are not multiples of 8. +/// +/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request +/// will be governed by a private watchdog timer that will cancel a queued job +/// or kill a running job if the hardware operation does not complete before +/// it times out. +/// +/// \param callback The callback to execute when the data move completes, or +/// NULL (0) to indicate no callback. +/// +/// \param arg The parameter to the callback routine; ignored if the \a +/// callback is NULL. +/// +/// \param options Options to control request priority, callback context and +/// blocking. +/// +/// This routine has no way to know if the OcbRequest structure is currently +/// in use, so this API should only be called on uninitialized or otherwise +/// idle OcbRequest structures. +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_OBJECT_OCB_REQUEST The \a request or \a queue were NULL (0), or +/// the \a queue is not an initialized OcbQueue. +/// +/// \retval -ASYNC_INVALID_ARGUMENT_OCB_REQUEST The \a data pointer is +/// NULL (0), or the number of bytes is not a multiple of 8. +/// +/// See async_request_create() for other errors that may be returned by this +/// call. + +int +ocb_request_create(OcbRequest *request, + OcbQueue *queue, + uint64_t *data, + size_t bytes, + SsxInterval timeout, + AsyncRequestCallback callback, + void *arg, + int options) +{ + int rc; + AsyncRunMethod run_method = 0; // Make GCC Happy + AsyncQueue *async_queue = (AsyncQueue *)queue; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((request == 0) || + (queue == 0) || + !(async_queue->engine & ASYNC_ENGINE_OCB), + ASYNC_INVALID_OBJECT_OCB_REQUEST); + SSX_ERROR_IF((data == 0) || + (bytes % 8), + ASYNC_INVALID_ARGUMENT_OCB_REQUEST); + } + + switch (async_queue->engine) { + + case ASYNC_ENGINE_OCB_PULL0: + case ASYNC_ENGINE_OCB_PULL1: + case ASYNC_ENGINE_OCB_PULL2: + run_method = ocb_write_method; + break; + + case ASYNC_ENGINE_OCB_PUSH0: + case ASYNC_ENGINE_OCB_PUSH1: + case ASYNC_ENGINE_OCB_PUSH2: + run_method = ocb_read_method; + break; + } + + rc = async_request_create(&(request->request), + async_queue, + run_method, + ocb_async_error_method, + timeout, + callback, + arg, + options); + + request->data = data; + request->bytes = bytes; + + return rc; +} + + +/// Schedule a request on an OCB circular queue. +/// +/// \param request An initialized OcbRequest +/// +/// Note : As long as the OcbRequest is idle, the application is free to +/// directly change the \a data and \a bytes fields to read/write different +/// numbers of bytes to/from different locations the next time the request is +/// scheduled. +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_ARGUMENT_OCB_SCHEDULE The number of \a bytes +/// currently requested is not a multiple of 8. +/// +/// See async_request_schedule() for documentation of other errors + +int +ocb_request_schedule(OcbRequest *request) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((request->bytes % 8), ASYNC_INVALID_ARGUMENT_OCB_SCHEDULE); + } + + request->current = request->data; + request->remaining = request->bytes; + + return async_request_schedule((AsyncRequest *)request); +} + + +//////////////////////////////////////////////////////////////////////////// +// OcbQueue +//////////////////////////////////////////////////////////////////////////// + +/// Reset an OCB circular PUSH (read) queue +/// +/// This API is normally used during initialization, and assumes that all of +/// the parameters are valid. It resets and reprograms the hardware +/// associated with an OCB circular buffer to be consistent with the queue +/// engine, base address, length and interrupt protocol. The queue is enabled +/// and its interrupts are disabled. Any data in the queue will be silently +/// lost. +/// +/// Note that this API \e does \e not put the OCB channel into circular mode - +/// the communication method is controlled by the communication partner. +/// +/// The function of this routine is to write a new value into the OCB Stream +/// Push Control/Status register, which as a side effect resets the circular +/// buffer. The base register is also set up. + +void +ocb_read_engine_reset(OcbQueue *queue, size_t cq_length, int protocol) +{ + ocb_ocbshcsn_t cs; + + // Disable interrupts and disable and clear the queue. The queue length + // field is updated (for informational purposes). Interrupts will be + // re-enabled when requests are made for the queue. + + ssx_irq_disable(queue->irq); + + queue->cq_length = cq_length; + + cs.value = 0; + out32(G_ocb_ocbsxcsn[queue->engine], cs.value); + + + // Reinitialize the data buffer base address register + + out32(G_ocb_ocbsxbrn[queue->engine], (uint32_t)(queue->cq_base)); + + + // Reprogram and reenable/reset the queue + + if (protocol == OCB_INTERRUPT_PROTOCOL_LAZY) { + cs.fields.push_intr_action = OCB_INTR_ACTION_FULL; + } else { + cs.fields.push_intr_action = OCB_INTR_ACTION_NOT_EMPTY; + } + + cs.fields.push_length = cq_length - 1; + cs.fields.push_enable = 1; + + out32(G_ocb_ocbsxcsn[queue->engine], cs.value); +} + + +/// Reset an OCB circular PULL (write) queue +/// +/// This API is normally used during initialization, and assumes that all of +/// the parameters are valid. It resets and reprograms the hardware +/// associated with an OCB circular buffer to be consistent with the queue +/// engine, base address, length and interrupt protocol. The queue is enabled +/// and its interrupts are disabled. Any data in the queue will be silently +/// lost. +/// +/// Note that this API \e does \e not put the OCB channel into circular mode - +/// the communication method is controlled by the communication partner. +/// +/// The function of this routine is to write a new value into the OCB Stream +/// Pull Control/Status register, which as a side effect resets the circular +/// buffer. The base register is also set up. + +void +ocb_write_engine_reset(OcbQueue *queue, size_t cq_length, int protocol) +{ + ocb_ocbslcsn_t cs; + + // Disable interrupts and disable and clear the queue. The queue length + // field is updated (for informational purposes). Interrupts will be + // re-enabled when requests are made for the queue. + + ssx_irq_disable(queue->irq); + + queue->cq_length = cq_length; + + cs.value = 0; + out32(G_ocb_ocbsxcsn[queue->engine], cs.value); + + + // Reinitialize the data buffer base address register + + out32(G_ocb_ocbsxbrn[queue->engine], (uint32_t)(queue->cq_base)); + + + // Reprogram and reenable/reset the queue + + if (protocol == OCB_INTERRUPT_PROTOCOL_LAZY) { + cs.fields.pull_intr_action = OCB_INTR_ACTION_EMPTY; + } else { + cs.fields.pull_intr_action = OCB_INTR_ACTION_NOT_FULL; + } + + cs.fields.pull_length = cq_length - 1; + cs.fields.pull_enable = 1; + + out32(G_ocb_ocbsxcsn[queue->engine], cs.value); +} + + +/// Create (initialize) an OcbQueue +/// +/// \param queue An uninitialized or otherwise idle OcbQueue +/// +/// \param engine A valid OCB engine id +/// +/// \param cq_base The base address of the circular queue data area for the +/// queue. This address must be 8-byte aligned for write queues. Read queues +/// must be cache-line aligned and a multiple of the cache line in size. +/// +/// \param cq_length The length of the circular queue measured in 8-byte +/// increments. +/// +/// \param protocol The interrupt protocol, either OCB_PUSH_PULL_PROTOCOL_LAZY +/// or OCB_PUSH_PULL_PROTOCOL_AGGRESSIVE. Lazy means that read queues only +/// interrupt when empty, and write queues only interrupt when full. +/// Agressive means that read queues interrupt when not empty and write queues +/// interrupt when not full. In general the lazy read protocol will only work +/// for 1) queues of length 1, where lazy == aggressive, and 2) protocols +/// where a known fixed number of 8-byte entries is always expected to be +/// received. +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_OBJECT_OCB_QUEUE The \a queue was NULL (0). +/// +/// \retval -ASYNC_INVALID_ARGUMENT_OCB_QUEUE The \a cq_base is not properly +/// aligned, or the \a cq_length is invalid, or the \a protocol is invalid. +/// +/// \retval -ASYNC_INVALID_ENGINE_OCB The \a engine is not an OCB engine. +/// +/// Other errors may be returned by async_queue_create(). + +int +ocb_queue_create(OcbQueue *queue, + int engine, + uint64_t *cq_base, + size_t cq_length, + int protocol) +{ + AsyncQueue *async_queue = (AsyncQueue *)queue; + int align_mask = 0; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_OCB_QUEUE); + SSX_ERROR_IF((cq_length < OCB_PUSH_PULL_LENGTH_MIN) || + (cq_length > OCB_PUSH_PULL_LENGTH_MAX) || + ((protocol != OCB_INTERRUPT_PROTOCOL_LAZY) && + (protocol != OCB_INTERRUPT_PROTOCOL_AGGRESSIVE)), + ASYNC_INVALID_ARGUMENT_OCB_QUEUE); + } + + queue->cq_base = cq_base; + queue->cq_length = cq_length; + + switch (engine) { + + // These are the read engines from OCC's perspective. + + case ASYNC_ENGINE_OCB_PUSH0: + queue->irq = PGP_IRQ_STRM0_PUSH; + queue->engine = OCB_ENGINE_PUSH0; + goto read_engine; + + case ASYNC_ENGINE_OCB_PUSH1: + queue->irq = PGP_IRQ_STRM1_PUSH; + queue->engine = OCB_ENGINE_PUSH1; + goto read_engine; + + case ASYNC_ENGINE_OCB_PUSH2: + queue->irq = PGP_IRQ_STRM2_PUSH; + queue->engine = OCB_ENGINE_PUSH2; + goto read_engine; + + read_engine: + align_mask = CACHE_LINE_SIZE - 1; + async_queue_create(async_queue, engine); + ocb_read_engine_reset(queue, cq_length, protocol); + break; + + // These are the write engines from OCC's perspective. + + case ASYNC_ENGINE_OCB_PULL0: + queue->irq = PGP_IRQ_STRM0_PULL; + queue->engine = OCB_ENGINE_PULL0; + goto write_engine; + + case ASYNC_ENGINE_OCB_PULL1: + queue->irq = PGP_IRQ_STRM1_PULL; + queue->engine = OCB_ENGINE_PULL1; + goto write_engine; + + case ASYNC_ENGINE_OCB_PULL2: + queue->irq = PGP_IRQ_STRM2_PULL; + queue->engine = OCB_ENGINE_PULL2; + goto write_engine; + + write_engine: + align_mask = 8 - 1; + async_queue_create(async_queue, engine); + ocb_write_engine_reset(queue, cq_length, protocol); + break; + + default: + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(1, ASYNC_INVALID_ENGINE_OCB); + } + } + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(((uint32_t)cq_base & align_mask) != 0, + ASYNC_INVALID_ARGUMENT_OCB_QUEUE2); + } + + return 0; +} + + +// The interrupt handler for asynchronous OCB CQ requests +// +// The circular buffer interupts are level sensitive, active high. There is +// really no way to 'clear' them as they indicate a permanent status - so +// instead they need to be enabled and disabled. Interrupts are enabled by the +// run methods and disabled by the interrupt handlers once all data has been +// transferred (or in the event of an error). +// +// This interrupt handler can process up to 256 bytes at once, plus the +// overhead of scheduling the next job when this one completes. If interrupt +// latency becomes a problem then this process could be run with interrupt +// preemption enabled. + +SSX_IRQ_FAST2FULL(ocb_async_handler, ocb_async_handler_full); + +void +ocb_async_handler_full(void *arg, SsxIrqId irq, int priority) +{ + AsyncQueue *async_queue = (AsyncQueue*)arg; + OcbQueue *queue = (OcbQueue*)async_queue; + OcbRequest *request = (OcbRequest*)(async_queue->current); + size_t processed; + int rc; + + if (SSX_ERROR_CHECK_KERNEL && (request == 0)) { + SSX_PANIC(ASYNC_PHANTOM_INTERRUPT_OCB); + } + + if (queue->engine % 2) { + rc = ocb_write(queue, request->current, request->remaining, &processed); + } else { + rc = ocb_read(queue, request->current, request->remaining, &processed); + } + + if (rc) { + + ssx_irq_disable(queue->irq); + async_error_handler(async_queue, ASYNC_REQUEST_STATE_FAILED); + + } else if (processed == request->remaining) { + + ssx_irq_disable(queue->irq); + async_handler(async_queue); + + } else { + + request->current += (processed / 8); + request->remaining -= processed; + } +} + + +// The interrupt handler for the OCB error interrupt. +// +// There is one interrupt that covers all OCB indirect channels as well as the +// direct bridge. When this interrupt fires we try to determine which unit is +// responsible. If the error appears to be associated with a job running as +// part of the async mechanism then we let the async_error_handler() mechanism +// operate, otherwise simply collect FFDC. The \a error field of the FFDC +// structure stops non-queued read/write requests. Note that we kill both read +// and write jobs without regard to the error. +// +// If the error is due to the direct bridge we collect FFDC, but can't really +// do anything else. + +/// \todo What action to take for bridge errors? + + +SSX_IRQ_FAST2FULL(ocb_error_handler, ocb_error_handler_full); + +void +ocb_error_handler_full(void *arg, SsxIrqId irq, int priority) +{ + ocb_occlfir_t fir; + int channel; + AsyncQueue* queue; + + ssx_irq_status_clear(irq); + + getscom(OCB_OCCLFIR, &(fir.value)); + + for (channel = 0; channel < OCB_INDIRECT_CHANNELS; channel++) { + if (fir.value & (OCB_OCCLFIR_OCB_IDC0_ERROR >> channel)) { + + queue = (AsyncQueue*)(&(G_ocb_read_queue[channel])); + if (queue->state == ASYNC_QUEUE_STATE_RUNNING) { + async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED); + } else { + ocb_ffdc(channel); + } + + queue = (AsyncQueue*)(&(G_ocb_write_queue[channel])); + if (queue->state == ASYNC_QUEUE_STATE_RUNNING) { + async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED); + } else { + ocb_ffdc(channel); + } + } + } + + if (fir.fields.ocb_db_oci_timeout | + fir.fields.ocb_db_oci_read_data_parity | + fir.fields.ocb_db_oci_slave_error | + fir.fields.ocb_pib_addr_parity_err | + fir.fields.ocb_db_pib_data_parity_err) { + + ocb_ffdc(-1); + } +} + + +//////////////////////////////////////////////////////////////////////////// +// Initialization +//////////////////////////////////////////////////////////////////////////// + +void +async_ocb_initialize(OcbQueue *queue, int engine, + uint64_t *buffer, size_t length, int protocol) +{ + ocb_queue_create(queue, engine, buffer, length, protocol); + async_level_handler_setup(ocb_async_handler, + (void *)queue, + queue->irq, + SSX_NONCRITICAL, + SSX_IRQ_POLARITY_ACTIVE_HIGH); + // Driver manages IRQ enable/disable +} diff --git a/src/ssx/pgp/pgp_async_pba.c b/src/ssx/pgp/pgp_async_pba.c new file mode 100755 index 0000000..14b5619 --- /dev/null +++ b/src/ssx/pgp/pgp_async_pba.c @@ -0,0 +1,1201 @@ +// $Id: pgp_async_pba.c,v 1.2 2014/02/03 01:30:34 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_async_pba.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_async_pba.c +/// \brief Async device drivers for the PBA block copy engines and PBAX + +#include "ssx.h" + +//////////////////////////////////////////////////////////////////////////// +// Global Data +//////////////////////////////////////////////////////////////////////////// + +BceQueue G_pba_bcue_queue; +BceQueue G_pba_bcde_queue; + +PbaxQueue G_pbax_read_queue[PBAX_QUEUES]; + + +//////////////////////////////////////////////////////////////////////////// +// Local Data +//////////////////////////////////////////////////////////////////////////// + + +/// Combined FFDC for all PBA subunits +static PbaUnitFfdc G_pba_ffdc = {{{{{0}}}}}; + + +PBAX_CQ_READ_BUFFER(G_pbax_read0_buffer, PBAX_READ0_LENGTH); +PBAX_CQ_READ_BUFFER(G_pbax_read1_buffer, PBAX_READ1_LENGTH); + +// The generic driver code stores an engine-specfic engine ID in the +// queue. Here arrays are set up that contain the OCI control register +// addresses for an engine indexed by the queue-specific value. +// +/// \todo Once the designers actually define register addresses, see about +/// modifying these tables to be macros instead. +/// +/// \todo Actually, why don't we just store this data directly in the queue? + +/// PBA BCDE/BCUE PowerBus BAR[0..31] +static const SsxAddress G_bce_pbadr[BCE_ENGINES] = + {PBA_BCDE_PBADR, PBA_BCUE_PBADR}; + +/// PBA BCDE/BCUE OCI BAR +static const SsxAddress G_bce_ocibar[BCE_ENGINES] = + {PBA_BCDE_OCIBAR, PBA_BCUE_OCIBAR}; + +/// PBA BCDE/BCUE SET register +static const SsxAddress G_bce_set[BCE_ENGINES] = + {PBA_BCDE_SET, PBA_BCUE_SET}; + +/// PBA BCDE/BCUE Control register +static const SsxAddress G_bce_ctl[BCE_ENGINES] = + {PBA_BCDE_CTL, PBA_BCUE_CTL}; + +/// PBA BCDE/BCUE Status register +static const SsxAddress G_bce_stat[BCE_ENGINES] = + {PBA_BCDE_STAT, PBA_BCUE_STAT}; + +/// PBAX Push Queue Control/Status Register addresses +static const SsxAddress G_pba_xshcsn[PBAX_ENGINES] = + {PBA_XSHCS0, PBA_XSHCS1}; + +/// PBAX Push Queue Base Register addresses +static const SsxAddress G_pba_xshbrn[PBAX_ENGINES] = + {PBA_XSHBR0, PBA_XSHBR1}; + +/// PBAX Push Queue Increment Register addresses +static const SsxAddress G_pba_xshincn[PBAX_ENGINES] = + {PBA_XSHINC0, PBA_XSHINC1}; + + +//////////////////////////////////////////////////////////////////////////// +// PBA FFDC Structures +//////////////////////////////////////////////////////////////////////////// + +// NB: Collection of FFDC for PBA will be very time consuming due to the large +// amount of information required to fully diagnose any problem. This will be +// done in a critical interrupt so it may have some impact on micro-timescale +// realtime operations. + +// Collect PBA common FFDC +// +// Most of this is just collection of all of the setup registers required to +// diagnose problems with the bridge and block copy engines. Not all of this +// data is required for PBAX errors but we collect it anyway. +// +// FFDC is only collected for the first error, until the error flag is reset. + +static void +pba_common_ffdc(PbaCommonFfdc* ffdc) +{ + int i; + + if (ffdc->error == 0) { + + oci_ffdc(&(ffdc->oci_ffdc), OCI_MASTER_ID_PBA); + + ffdc->mode.value = in64(PBA_MODE); + + for (i = 0; i < PBA_READ_BUFFERS; i++) { + getscom(PBA_RBUFVALN(i), &(ffdc->rbufval[i].value)); + } + + for (i = 0; i < PBA_WRITE_BUFFERS; i++) { + getscom(PBA_WBUFVALN(i), &(ffdc->wbufval[i].value)); + } + + for (i = 0; i < PBA_BARS; i++) { + getscom(PBA_BARN(i), &(ffdc->bar[i].value)); + getscom(PBA_BARMSKN(i), &(ffdc->barmsk[i].value)); + } + + getscom(PBA_FIR, &(ffdc->fir.value)); + getscom(PBA_ERRPT0, &(ffdc->errpt0.value)); + getscom(PBA_ERRPT1, &(ffdc->errpt1.value)); + getscom(PBA_ERRPT2, &(ffdc->errpt2.value)); + + ffdc->error = 1; + } +} + + +// Collect FFDC for generic PBA bridge errors +// +// This extends the common collection with PBA slave control/status +// information. + +static void +pba_bridge_ffdc(PbaBridgeFfdc* ffdc) +{ + int i; + + if (ffdc->common.error == 0) { + + pba_common_ffdc(&(ffdc->common)); + + ffdc->slvrst.value = in64(PBA_SLVRST); + + for (i = 0; i > PBA_SLAVES; i++) { + ffdc->slvctl[i].value = in64(PBA_SLVCTLN(i)); + } + } +} + + +// Collect FFDC for a particular Block Copy Engine +// +// The engine ID here is either 0 (BCDE) or 1 (BCUE) + +static void +bce_ffdc(BceFfdc* ffdc, int engine) +{ + if (ffdc->common.error == 0) { + + pba_common_ffdc(&(ffdc->common)); + + ffdc->ctl.value = in64(G_bce_ctl[engine]); + ffdc->set.value = in64(G_bce_set[engine]); + ffdc->pbadr.value = in64(G_bce_pbadr[engine]); + ffdc->stat.value = in64(G_bce_stat[engine]); + } +} + + +// Collect FFDC for PBAX send + +static void +pbax_send_ffdc(PbaxSendFfdc* ffdc) +{ + if (ffdc->common.error == 0) { + + pba_common_ffdc(&(ffdc->common)); + + ffdc->xcfg.value = in64(PBA_XCFG); + ffdc->xsndtx.value = in64(PBA_XSNDTX); + ffdc->xsndstat.value = in64(PBA_XSNDSTAT); + } +} + + +// Collect FFDC for PBAX receive +// +// The drivers currently do not distinguish errors between the two receive +// queues as the hardware design does not provide a clean separation. + +static void +pbax_receive_ffdc(PbaxReceiveFfdc* ffdc) +{ + int i; + + if (ffdc->common.error == 0) { + + pba_common_ffdc(&(ffdc->common)); + + ffdc->xcfg.value = in64(PBA_XCFG); + ffdc->xrcvstat.value = in64(PBA_XRCVSTAT); + + for (i = 0; i < PBAX_ENGINES; i++) { + ffdc->xshbrn[i].value = in64(PBA_XSHBRN(i)); + ffdc->xshcsn[i].value = in64(PBA_XSHCSN(i)); + } + } +} + + +//////////////////////////////////////////////////////////////////////////// +// BceRequest +//////////////////////////////////////////////////////////////////////////// + +// Start a request running on a PBA Block Copy Engine +// +// \param queue A BceQueue upcast to an AsyncQueue +// +// \param request A BceRequest upcast to an AsyncRequest +// +// This routine takes a Bce objects cast to Async objects so that it can be +// called from the generic Async interrupt handler. +// +// This is an internal API. This routine must be called from a context where +// critical interrupts are disabled. Prior to this call, scheduling code will +// have installed the new request as the \a current request of the queue, and +// marked both the queue and the request as running. +// +// The PBA driver handles requests that require multiple runs of the PBA to +// complete the request. Starting a PBA job requires setting up 3 registers, +// hitting the "go" bit, and computing the amount of work remaining. +// +// Note that PBA will signal an error and lock up the system if the START bit +// is written while a BC-engine is running. + +// Recall that the engines have identical control structures with identical +// relative offsets between registers. So we use BCDE offsets and BCDE +// register layout structures, but they work for BCUE as well. + +static int +bce_async_run_method(AsyncRequest *async_request) +{ + BceQueue *queue = (BceQueue *)(async_request->queue); + BceRequest *request = (BceRequest *)async_request; + int rc, engine; + pba_bcde_pbadr_t pbadr; + pba_bcde_set_t set; + pba_bcde_ctl_t ctl; + size_t to_write; + + + if (request->remaining == 0) { + + rc = -ASYNC_REQUEST_COMPLETE; + + } else { + + to_write = MIN(request->remaining, PBA_BCE_SIZE_MAX); + + // Create the address offset register. The PowerBus offset is the + // cache-line address of the stored offset (ex the OCI region bits). + + pbadr.value = 0; + + pbadr.fields.pb_offset = + (request->next_bridge_address & 0x3FFFFFFF) / + POWERBUS_CACHE_LINE_SIZE; + + pbadr.fields.extaddr = + request->extended_address.fields.extended_address; + + // Create the setup register + + set.value = 0; + + set.fields.copy_length = to_write / POWERBUS_CACHE_LINE_SIZE; + + // Set the START bit + + ctl.value = PBA_BCDE_CTL_START; + + // Start the BCE + + engine = queue->engine; + out64(G_bce_pbadr[engine], pbadr.value); + out32(G_bce_ocibar[engine], request->next_oci_address); + out32(G_bce_set[engine], set.words.high_order); + out32(G_bce_ctl[engine], ctl.words.high_order); + + // Update the work remaining to be done. + + request->remaining -= to_write; + if (request->remaining != 0) { + request->next_bridge_address += to_write; + request->next_oci_address += to_write; + } + + rc = 0; + } + + return rc; +} + + +// The async error method for Block Copy Engines +// +// Collect FFDC and stop the engine. The return of -1 will disable the +// channel associated with the request. The application will need to decide +// whether to restart the queue. + +static int +bce_async_error_method(AsyncRequest *request) +{ + BceQueue *queue = (BceQueue*)(request->queue); + int engine = queue->engine; + + if (engine == BCE_ENGINE_BCDE) { + + bce_ffdc(&(G_pba_ffdc.bcde), engine); + out32(PBA_BCDE_CTL, PBA_BCDE_CTL_STOP >> 32); + + } else { + + bce_ffdc(&(G_pba_ffdc.bcue), engine); + out32(PBA_BCUE_CTL, PBA_BCUE_CTL_STOP >> 32); + + } + + return -1; +} + + +/// Create a request for a PBA Block Copy engine +/// +/// \param request An uninitialized or otherwise idle BceRequest. +/// +/// \param queue An initialized BceQueue. +/// +/// \param bridge_address The 32-bit bridge address that is translated to +/// a PowerBus address associated with the copy. This address must be a +/// PowerBus cache (128-byte) aligned address. +/// +/// \param oci_address The 32-bit OCI address associated with the copy. This +/// address must be 128-byte aligned. +/// +/// \param bytes The number of bytes to move. This must be a multiple of 128, +/// and the size must not obviously overflow the OCI address or the bridge +/// address. +/// +/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request +/// will be governed by a private watchdog timer that will cancel a queued job +/// or kill a running job if the hardware operation does not complete before +/// it times out. +/// +/// \param callback The callback to execute when the PBA copy completes, or +/// NULL (0) to indicate no callback. +/// +/// \param arg The parameter to the callback routine; ignored if the \a +/// callback is NULL. +/// +/// \param options Options to control request priority and callback context. +/// +/// Note that the setup for the BC engines includes an extended address and a +/// PowerBus maximum priority. This API sets these to +/// the default values in the request. If non-default values are required, +/// they will need to be installed in the structure explicitly before +/// scheduling. +/// +/// This routine has no way to know if the BceRequest structure is currently +/// in use, so this API should only be called on uninitialized or otherwise +/// idle GpeRequest structures. +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_OBJECT_BCE_REQUEST The \a request was NULL (0), +/// or the \a queue was NULL (0) or not a BceQueue. +/// +/// See async_request_create() for other errors that may be returned by this +/// call. + +int +bce_request_create(BceRequest *request, + BceQueue *queue, + uint32_t bridge_address, + uint32_t oci_address, + size_t bytes, + SsxInterval timeout, + AsyncRequestCallback callback, + void *arg, + int options) +{ + int rc; + AsyncQueue *async_queue = (AsyncQueue *)queue; + + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((request == 0) || + (queue == 0) || + !(async_queue->engine & ASYNC_ENGINE_BCE), + ASYNC_INVALID_OBJECT_BCE_REQUEST); + } + + rc = async_request_create(&(request->request), + async_queue, + bce_async_run_method, + bce_async_error_method, + timeout, + callback, + arg, + options); + + request->bridge_address = bridge_address; + request->oci_address = oci_address; + request->bytes = bytes; + request->extended_address.value = 0; + + return rc; +} + + +//////////////////////////////////////////////////////////////////////////// +// BceQueue +//////////////////////////////////////////////////////////////////////////// + +/// Create (initialize) a BceQueue +/// +/// \param queue An uninitialized of otherwise idle BceQueue +/// +/// \param engine Either ASYNC_ENGINE_PBA_BCDE or ASYNC_ENGINE_PBA_BCUE +/// +/// This API initializes the BceQueue structure based on the engine +/// provided. There is really no special hardware initialization required as +/// the BC-engines are pretty simple data movers. +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_OBJECT_BCE_QUEUE The \a queue was NULL (0). +/// +/// \retval -ASYNC_INVALID_ENGINE_BCE The \a engine is not a PBA engine. + +int +bce_queue_create(BceQueue *queue, + int engine) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_BCE_QUEUE); + } + + switch (engine) { + + case ASYNC_ENGINE_BCDE: + async_queue_create(&(queue->queue), engine); + queue->engine = BCE_ENGINE_BCDE; + break; + + case ASYNC_ENGINE_BCUE: + async_queue_create(&(queue->queue), engine); + queue->engine = BCE_ENGINE_BCUE; + break; + + default: + if (SSX_ERROR_CHECK_API) { + SSX_ERROR(ASYNC_INVALID_ENGINE_BCE); + } + break; + } + + return 0; +} + + +/// Schedule a request on a PBA block-copy engine +/// +/// Note : As long as the BceRequest is idle, the application is free to +/// directly change the \a bridge_address, \a oci_address and \a bytes fields to +/// read/write different numbers of bytes to/from different locations the next +/// time the request is scheduled. +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_ARGUMENT_BCE_SCHEDULE Either the \a bridge_address +/// is not 128-byte aligned, or the OCI address is not 128-byte aligned, or the +/// number of bytes is not a multiple of 128. +/// +/// See async_request_schedule() for documentation of other errors + +int +bce_request_schedule(BceRequest *request) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((request->bridge_address % POWERBUS_CACHE_LINE_SIZE) || + (request->oci_address % POWERBUS_CACHE_LINE_SIZE) || + (request->bytes % POWERBUS_CACHE_LINE_SIZE), + ASYNC_INVALID_ARGUMENT_BCE_SCHEDULE); + } + + request->next_bridge_address = request->bridge_address; + request->next_oci_address = request->oci_address; + request->remaining = request->bytes; + + return async_request_schedule((AsyncRequest *)request); +} + + +// The interrupt handler for asynchronous PBA Block Copy requests +// +// BC-engine 'done' interrupts are level-sensitive active high, so they need +// to be cleared in the PBA by writing a 0 to the CTL register. We also get +// the PBA 'done' even when jobs are killed, but the cancel/kill code is +// responsible for setting the \a completion_state of the request. +// +// We only go to the generic handler once all data has been transferred. + +SSX_IRQ_FAST2FULL(bce_async_handler, bce_async_handler_full); + +void +bce_async_handler_full(void *arg, SsxIrqId irq, int priority) +{ + AsyncQueue *async_queue = (AsyncQueue *)arg; + AsyncRequest *async_current = (AsyncRequest *)async_queue->current; + BceQueue *queue = (BceQueue *)async_queue; + + out32(G_bce_ctl[queue->engine], 0); + + if (SSX_ERROR_CHECK_KERNEL && (async_current == 0)) { + SSX_PANIC(ASYNC_PHANTOM_INTERRUPT_BCE); + } + + if (async_current->run_method(async_current) == -ASYNC_REQUEST_COMPLETE) { + async_handler(async_queue); + } +} + + +//////////////////////////////////////////////////////////////////////////// +// PbaxRequest +//////////////////////////////////////////////////////////////////////////// + +/// Non-blocking read from a PBAX PUSH (read) queue +/// +/// \param queue The target PbaxQueue +/// +/// \param buf The caller's data buffer to receive the read data +/// +/// \param bytes The maximum number of bytes to read. This value should be an +/// even multiple of 8, as this API always reads multiples of 8 bytes. +/// +/// \param read The number of bytes actually copied from the device buffer to +/// the caller's buffer. This may be returned as any value from 0 to \a +/// bytes in multiples of 8 bytes. +/// +/// pbax_read() implements a non-blocking copy of data from a PBAX read (PUSH) +/// queue data area to the caller's data area, with the side effect of +/// advancing the hardware queue pointers. pbax_read() does not implement +/// locking, critical sections or any other type of synchronization for access +/// to the PBAX queue data. +/// +/// pbax_read() returns the error code -ASYNC_PBAX_ERROR_OLD or +/// -ASYNC_PBAX_ERROR_NEW if PBAX receive error status is asserted. +/// The error return code may be disjoint from the actual +/// read: If data is available it may be copied to the caller's buffer, but +/// this data should always be considered corrupted in the event of an error +/// return code. +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_READ The number of \a bytes is not +/// an even multiple of 8. +/// +/// \retval -ASYNC_PBAX_ERROR_OLD The PBA shows pre-existing error status +/// +/// \retval -ASYNC_PBAX_ERROR_NEW The PBA shows current error status +/// +/// \todo Once the HW design is finalized, we might consider modifying the +/// error behavior to only return an error status if the receive error was +/// associated with this particular queue. + +int +pbax_read(PbaxQueue* queue, void* buf, size_t bytes, size_t* read) +{ + pba_xshcsn_t csr; + pba_xrcvstat_t rsr; + unsigned qlen, read_ptr, write_ptr, to_read; + uint64_t *pcq, *pbuf; + int rc; + + do { + + rc = 0; + *read = 0; + + // If pre-existing errors exist then immediately abort the read. + + rsr.words.high_order = in32(PBA_XRCVSTAT); + if (rsr.fields.rcv_error) { + pbax_receive_ffdc(&(G_pba_ffdc.pbax_receive)); + rc = -ASYNC_PBAX_ERROR_OLD; + break; + } + + if (bytes % 8) { + rc = -ASYNC_INVALID_ARGUMENT_PBAX_READ; + break; + } + + // Determine the number of doubleword entries remaining to be read in + // the queue. The driver does not keep state, but instead reinterprets + // the control/status register each time the read method is called. + + // This may be confusing - remember that 'push' is from the PowerBus + // perspective - here we use 'read' from OCC's perspective. + + csr.words.high_order = in32(G_pba_xshcsn[queue->engine]); + + qlen = csr.fields.push_length + 1; + read_ptr = csr.fields.push_read_ptr; + + if (csr.fields.push_empty) { + break; + + } else if (csr.fields.push_full) { + to_read = qlen; + + } else { + write_ptr = csr.fields.push_write_ptr; + if (read_ptr > write_ptr) { + to_read = qlen - (read_ptr - write_ptr); + } else { + to_read = write_ptr - read_ptr; + } + } + + // Copy the data from the CQ memory area. For simplicty of dealing with + // cache management each doubleword invokes a line invalidate before + // refetching the fresh data from memory. Alignment requirements enforced + // on the data buffer guarantee the buffers are cache-line aligned and + // each doubleword is fully contained in a single D-cache line. + // + // Here the code models the evolution of the read_ptr as each datum is + // copied from the queue. + + pbuf = (uint64_t*) buf; + while (bytes && to_read--) { + + read_ptr++; + if (read_ptr == qlen) { + read_ptr = 0; + } + pcq = queue->cq_base + read_ptr; + + dcache_invalidate_line(pcq); + *pbuf++ = *pcq; + out32(G_pba_xshincn[queue->engine], 0); + + bytes -= 8; + *read += 8; + } + } while(0); + + // Check for errors that occurred during the read + + rsr.words.high_order = in32(PBA_XRCVSTAT); + if (rsr.fields.rcv_error) { + pbax_receive_ffdc(&(G_pba_ffdc.pbax_receive)); + rc = -ASYNC_PBAX_ERROR_NEW; + } + + return rc; +} + + +// This is the internal 'run method' for reading through a PBAX circular +// queue. The run method simply enables the IRQ. The interrupt handler reads +// data from the queue and leaves the interrupt enabled until the read is +// satisfied. + +int +pbax_read_method(AsyncRequest *async_request) +{ + PbaxRequest *request = (PbaxRequest*)async_request; + PbaxQueue *queue = (PbaxQueue*)(async_request->queue); + int rc; + + if (request->bytes == 0) { + rc = -ASYNC_REQUEST_COMPLETE; + } else { + ssx_irq_enable(queue->irq); + rc = 0; + } + return rc; +} + + +// The async error method for PBAX +// +// Collect FFDC. + +static int +pbax_async_error_method(AsyncRequest *request) +{ + pbax_receive_ffdc(&(G_pba_ffdc.pbax_receive)); + return -1; +} + + +/// Create a request for a PBAX read queue +/// +/// \param request An uninitialized or otherwise idle PbaxRequest. +/// +/// \param queue An async queue for a PBAX read buffer. +/// +/// \param data A pointer to the data to where the data should be placed. +/// +/// \param bytes The (maximum) number of bytes of data to move. The PBAX read +/// queues always move multiples of 8 bytes, and the number of bytes must be a +/// multiple of 8. Higher-level abstractions will have to take care of cases +/// where the "actual" numbers of bytes are not multiples of 8. +/// +/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request +/// will be governed by a private watchdog timer that will cancel a queued job +/// or kill a running job if the hardware operation does not complete before +/// it times out. +/// +/// \param callback The callback to execute when the read completes, or +/// NULL (0) to indicate no callback. +/// +/// \param arg The parameter to the callback routine; ignored if the \a +/// callback is NULL. +/// +/// \param options Options to control request priority, callback context and +/// blocking. See the documentation for the PbaxRequest object for information +/// on the special ASYNC_NONBLOCKING_READ option. +/// +/// This routine has no way to know if the PbaxRequest structure is currently +/// in use, so this API should only be called on uninitialized or otherwise +/// idle PbaxRequest structures. +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_OBJECT_PBAX_REQUEST The \a request or \a queue +/// were NULL (0), or the \a queue is not an initialized PbaxQueue. +/// +/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_REQUEST The \a data pointer is +/// NULL (0), or the number of bytes is not a multiple of 8. +/// +/// See async_request_create() for other errors that may be returned by this +/// call. + +int +pbax_request_create(PbaxRequest* request, + PbaxQueue* queue, + uint64_t* data, + size_t bytes, + SsxInterval timeout, + AsyncRequestCallback callback, + void* arg, + int options) +{ + int rc; + AsyncQueue* async_queue = (AsyncQueue*)queue; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((request == 0) || + (queue == 0) || + !(async_queue->engine & ASYNC_ENGINE_PBAX), + ASYNC_INVALID_OBJECT_PBAX_REQUEST); + SSX_ERROR_IF((data == 0) || + (bytes % 8), + ASYNC_INVALID_ARGUMENT_PBAX_REQUEST); + } + + rc = async_request_create(&(request->request), + async_queue, + pbax_read_method, + pbax_async_error_method, + timeout, + callback, + arg, + options); + + request->data = data; + request->bytes = bytes; + + return rc; +} + + +/// Schedule a request on a PBAX read queue +/// +/// Note : As long as the PbaxRequest is idle, the application is free to +/// directly change the \a data and \a bytes fields to read different numbers of +/// bytes into different locations the next time the request is scheduled. +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_SCHEDULE The number of \a bytes +/// currently requested is not a multiple of 8. +/// +/// See async_request_schedule() for documentation of other errors + +int +pbax_request_schedule(PbaxRequest *request) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((request->bytes % 8),ASYNC_INVALID_ARGUMENT_PBAX_SCHEDULE); + } + + request->current = request->data; + request->remaining = request->bytes; + + return async_request_schedule((AsyncRequest *)request); +} + + +//////////////////////////////////////////////////////////////////////////// +// PbaxQueue +//////////////////////////////////////////////////////////////////////////// + +/// Disable a PBAX circular PUSH (read) queue +/// +/// \param queue An initialized PbaxQueue object. +/// +/// Disable the PBAX recieve mechanism for a particular PBAX receive queue. +/// Interrupts are disabled, and any data managed by the queue is effectively +/// lost. +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_OBJECT_PBAX_DISABLE The \a queue is NULL (0) +/// or otherwise invalid. + +int +pbax_queue_disable(PbaxQueue *queue) +{ + pba_xshcsn_t cs; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_PBAX_DISABLE); + } + + ssx_irq_disable(queue->irq); + + cs.value = 0; + out32(G_pba_xshcsn[queue->engine], cs.value); + + return 0; +} + + +/// Enable a PBAX circular PUSH (read) queue +/// +/// \param queue An initialized PbaxQueue object. +/// +/// This API reprograms the queue hardware in accordance with the values +/// present in the \a queue structure, and enables the queue to accept data. +/// Any previous record of data present in the queue will be lost. The queue +/// interrupt is also disabled by this API. +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_OBJECT_PBAX_DISABLE The \a queue is NULL (0) +/// or otherwise invalid. + +int +pbax_queue_enable(PbaxQueue *queue) +{ + int rc; + pba_xshcsn_t cs; + + rc = pbax_queue_disable(queue); + + if (!rc) { + + // Reinitialize the data buffer base address register and + // reprogram/re-enable the queue. + + out32(G_pba_xshbrn[queue->engine], (uint32_t)(queue->cq_base)); + + cs.value = 0; + + if (queue->protocol == PBAX_INTERRUPT_PROTOCOL_LAZY) { + cs.fields.push_intr_action = PBAX_INTR_ACTION_FULL; + } else { + cs.fields.push_intr_action = PBAX_INTR_ACTION_NOT_EMPTY; + } + + cs.fields.push_length = queue->cq_entries - 1; + cs.fields.push_enable = 1; + + out32(G_pba_xshcsn[queue->engine], cs.words.high_order); + } + return 0; +} + + +/// Create (initialize) a PbaxQueue abstraction +/// +/// \param queue An uninitialized or otherwise idle PbaxQueue +/// +/// \param engine A valid PBAX engine id +/// +/// \param cq_base The base address of the circular queue data area for the +/// queue. This address must be aligned to the next higher power-of-two of the +/// buffer size, with a minimum alignment of a cache line. +/// +/// \param cq_entries The number of 8-byte entries in the queue +/// +/// \param protocol The interrupt protocol, either PBAX_PUSH_PROTOCOL_LAZY or +/// PBAX_PUSH_PROTOCOL_AGGRESSIVE. Lazy means that read queues only interrupt +/// when full, and agressive means that read queues interrupt whenever they +/// are not empty. In general the lazy read protocol will only work for 1) +/// queues of length 1, where lazy == aggressive, and 2) protocols where a +/// known fixed number of 8-byte entries is always expected to be received. +/// +/// This API simply creates the PbaxQueue abstraction in the software space; +/// The API does not modify any harwdare state. To enable/disable the PBAX +/// hardware read queue use pbax_queue_enable(). +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_OBJECT_PBAX_QUEUE The \a queue was NULL (0). +/// +/// \retval -ASYNC_INVALID_ARGUMENT_PBAX_QUEUE The \a cq_base is not properly +/// aligned, or the \a cq_length is invalid, or the \a protocol is invalid. +/// +/// \retval -ASYNC_INVALID_ENGINE_PBAX The \a engine is not an PBAX engine. +/// +/// Other errors may be returned by async_queue_create(). + +int +pbax_queue_create(PbaxQueue *queue, + int engine, + uint64_t *cq_base, + size_t cq_entries, + int protocol) +{ + AsyncQueue *async_queue = (AsyncQueue *)queue; + + if (SSX_ERROR_CHECK_API) { + uint32_t align_mask = + POW2_32(MAX(CEILING_LOG2(cq_entries * 8), + LOG_CACHE_LINE_SIZE)) - 1; + + SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_PBAX_QUEUE); + SSX_ERROR_IF((((uint32_t)(cq_base) & align_mask) != 0) || + (cq_entries < PBAX_PUSH_LENGTH_MIN) || + (cq_entries > PBAX_PUSH_LENGTH_MAX) || + ((protocol != PBAX_INTERRUPT_PROTOCOL_LAZY) && + (protocol != PBAX_INTERRUPT_PROTOCOL_AGGRESSIVE)), + ASYNC_INVALID_ARGUMENT_PBAX_QUEUE); + } + + queue->cq_base = cq_base; + queue->cq_entries = cq_entries; + queue->protocol = protocol; + + switch (engine) { + + case ASYNC_ENGINE_PBAX_PUSH0: + queue->irq = PGP_IRQ_PBA_OCC_PUSH0; + queue->engine = PBAX_ENGINE_PUSH0; + break; + + case ASYNC_ENGINE_PBAX_PUSH1: + queue->irq = PGP_IRQ_PBA_OCC_PUSH1; + queue->engine = PBAX_ENGINE_PUSH1; + break; + + default: + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(1, ASYNC_INVALID_ENGINE_PBAX); + } + } + + async_queue_create(async_queue, engine); + + return 0; +} + + +// The interrupt handler for asynchronous PBAX requests +// +// The circular buffer interupts are level sensitive, active high. There is +// really no way to 'clear' them as they indicate a permanent status - so +// instead they need to be enabled and disabled. This is done by the read +// method. (Note that one could make them edge-triggered, but in general +// device drivers [including this one] would not work correctly if they were +// programmed that way.) +// +// This interrupt handler can process up to 256 bytes at once, plus the +// overhead of scheduling the next job when this one completes. If interrupt +// latency becomes a problem then this process could be run with interrupt +// preemption enabled. + +SSX_IRQ_FAST2FULL(pbax_async_handler, pbax_async_handler_full); + +void +pbax_async_handler_full(void *arg, SsxIrqId irq, int priority) +{ + AsyncQueue* async_queue = (AsyncQueue*)arg; + PbaxQueue* queue = (PbaxQueue*)async_queue; + PbaxRequest* request = (PbaxRequest*)(async_queue->current); + size_t read; + int rc; + + if (SSX_ERROR_CHECK_KERNEL && (request == 0)) { + SSX_PANIC(ASYNC_PHANTOM_INTERRUPT_PBAX); + } + + rc = pbax_read(queue, request->current, request->remaining, &read); + + if (rc) { + + ssx_irq_disable(queue->irq); + async_error_handler(async_queue, ASYNC_REQUEST_STATE_FAILED); + + } else if (read == request->remaining) { + + ssx_irq_disable(queue->irq); + async_handler(async_queue); + + } else { + + request->current += (read / 8); + request->remaining -= read; + } +} + + +// The interrupt handler for the PBA error interrupt. +// +// There is one error interrupt that covers all PBA function - the generic +// bridge, block copy engines and PBAX buffers. The PBA error pulses whenever +// new error bits are logged in the PBA FIR, so it is possible for OCC to log +// errors independently for the bridge, BCE and PBAX. +// +// When the PBA error interrupt fires we try to determine which unit is +// responsible for the error and take appropriate action. The analysis is +// currently not very deep, however it is not clear whether it is worth the +// time and code space required to do more than this. +// +// - If the error appears to be associated with either a BCDE or BCUE job +// running as part of the async mechanism then we let the +// async_error_handler() mechanism operate. As a side effect the indicated +// queue will be disabled. Note that further analysis (and storage space) +// might allow jobs to be restarted on that engine, but this is currently not +// done. +// +// - If the error appears to be associated with a PBAX send then the PBAX send +// mechanism is already effectively disabled by the fact that the send status +// register shows an error. FFDC is simply collected in this case. +// +// - If the error appears to be associated with a PBAX receive mechanism then +// both receive queues are stopped. The receive may or may not be using the +// job queues (the application may be polling using pbax_read()). +// +// If the error is due to the direct bridge we collect FFDC, but can't really +// do anything else. Since OCC will not use the PBA bridge at run time +// (except for lab-mode applications) this error is due either to a PORE +// engine or FSP using the dedicated trusted channel to mainstore. +// +// This code is assumed to be activated as a critical interrupt. + +/// \todo What to do for generic PBA errors? + +SSX_IRQ_FAST2FULL(pba_error_handler, pba_error_handler_full); + +void +pba_error_handler_full(void *arg, SsxIrqId irq, int priority) +{ + pba_fir_t fir; + pba_bcde_stat_t bcde_stat; + pba_bcue_stat_t bcue_stat; + pba_xsndstat_t xsndstat; + pba_xrcvstat_t xrcvstat; + int channel; + AsyncQueue* queue; + + ssx_irq_status_clear(irq); + + getscom(PBA_FIR, &(fir.value)); + bcde_stat.words.high_order = in32(PBA_BCDE_STAT); + bcue_stat.words.high_order = in32(PBA_BCUE_STAT); + xsndstat.words.high_order = in32(PBA_XSNDSTAT); + xrcvstat.words.high_order = in32(PBA_XRCVSTAT); + + queue = (AsyncQueue*)(&G_pba_bcde_queue); + if (bcde_stat.fields.error && + (queue->state == ASYNC_QUEUE_STATE_RUNNING)) { + async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED); + } + + queue = (AsyncQueue*)(&G_pba_bcue_queue); + if (bcue_stat.fields.error && + (queue->state == ASYNC_QUEUE_STATE_RUNNING)) { + async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED); + } + + if (xsndstat.fields.snd_error) { + pbax_send_ffdc(&G_pba_ffdc.pbax_send); + } + + if (xrcvstat.fields.rcv_error) { + for (channel = 0; channel < PBAX_CHANNELS; channel++) { + queue = (AsyncQueue*)(&G_pbax_read_queue[channel]); + if (queue->state == ASYNC_REQUEST_STATE_RUNNING) { + async_error_handler(queue, ASYNC_REQUEST_STATE_FAILED); + } else { + pbax_receive_ffdc(&G_pba_ffdc.pbax_receive); + } + } + } + + // Any FIR bits not already attributable to previously handled errors are + // assumed to be due to the generic bridge. + + if (fir.value & + ( + PBA_FIR_OCI_APAR_ERR || + PBA_FIR_PB_RDADRERR_FW || + PBA_FIR_PB_RDDATATO_FW || + PBA_FIR_PB_SUE_FW || + PBA_FIR_PB_UE_FW || + PBA_FIR_PB_CE_FW || + PBA_FIR_OCI_SLAVE_INIT || + PBA_FIR_OCI_WRPAR_ERR || + PBA_FIR_OCI_REREQTO || + PBA_FIR_PB_UNEXPCRESP || + PBA_FIR_PB_UNEXPDATA || + PBA_FIR_PB_PARITY_ERR || + PBA_FIR_PB_WRADRERR_FW || + PBA_FIR_PB_BADCRESP || + PBA_FIR_PB_ACKDEAD_FW || + PBA_FIR_PB_CRESPTO || + // PBA_FIR_BCUE_SETUP_ERR || + // PBA_FIR_BCUE_PB_ACK_DEAD || + // PBA_FIR_BCUE_PB_ADRERR || + // PBA_FIR_BCUE_OCI_DATAERR || + // PBA_FIR_BCDE_SETUP_ERR || + // PBA_FIR_BCDE_PB_ACK_DEAD || + // PBA_FIR_BCDE_PB_ADRERR || + // PBA_FIR_BCDE_RDDATATO_ERR || + // PBA_FIR_BCDE_SUE_ERR || + // PBA_FIR_BCDE_UE_ERR || + // PBA_FIR_BCDE_CE || + // PBA_FIR_BCDE_OCI_DATAERR || + PBA_FIR_INTERNAL_ERR || + PBA_FIR_ILLEGAL_CACHE_OP || + PBA_FIR_OCI_BAD_REG_ADDR || + // PBA_FIR_AXPUSH_WRERR || + // PBA_FIR_AXRCV_DLO_ERR || + // PBA_FIR_AXRCV_DLO_TO || + // PBA_FIR_AXRCV_RSVDATA_TO || + // PBA_FIR_AXFLOW_ERR || + // PBA_FIR_AXSND_DHI_RTYTO || + // PBA_FIR_AXSND_DLO_RTYTO || + // PBA_FIR_AXSND_RSVTO || + // PBA_FIR_AXSND_RSVERR || + PBA_FIR_FIR_PARITY_ERR || + PBA_FIR_FIR_PARITY_ERR2 + ) + ) { + + pba_bridge_ffdc(&(G_pba_ffdc.bridge)); + } +} + + +//////////////////////////////////////////////////////////////////////////// +// Initialization +//////////////////////////////////////////////////////////////////////////// + +void +async_bce_initialize(BceQueue *queue, int engine, SsxIrqId irq) +{ + bce_queue_create(queue, engine); + async_level_handler_setup(bce_async_handler, + (void *)queue, + irq, + SSX_CRITICAL, + SSX_IRQ_POLARITY_ACTIVE_HIGH); + ssx_irq_enable(irq); +} + + +void +async_pbax_initialize(PbaxQueue *queue, int engine, SsxIrqId irq, + uint64_t *buffer, size_t length, int protocol) +{ + pbax_queue_create(queue, engine, buffer, length, protocol); + pbax_queue_enable(queue); + async_level_handler_setup(pbax_async_handler, + (void *)queue, + irq, + SSX_NONCRITICAL, + SSX_IRQ_POLARITY_ACTIVE_HIGH); + // Driver or application manages IRQ enable/disable +} + + diff --git a/src/ssx/pgp/pgp_async_pore.c b/src/ssx/pgp/pgp_async_pore.c new file mode 100755 index 0000000..5f9b425 --- /dev/null +++ b/src/ssx/pgp/pgp_async_pore.c @@ -0,0 +1,644 @@ +// $Id: pgp_async_pore.c,v 1.5 2014/05/14 13:35:43 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_async_pore.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_async_pore.c +/// \brief PgP "async" drivers for PORE engines + +#include "ssx.h" + +//////////////////////////////////////////////////////////////////////////// +// Global Data +//////////////////////////////////////////////////////////////////////////// + +// The PORE queue objects. + +PoreQueue G_pore_gpe0_queue; +PoreQueue G_pore_gpe1_queue; +PoreQueue G_pore_slw_queue; + + +//////////////////////////////////////////////////////////////////////////// +// Local Data +//////////////////////////////////////////////////////////////////////////// + +/// PoreFlex entry point - See G_pore_flex_table. + +static uint32_t G_pore_flex_entry0 = PORE_BRAD_D0; + + +/// Entry 0 of the PoreFlex branch table +/// +/// This variable is the only thing we represent of the branch table for PORE +/// flex requests. PoreFlex requests are forbidden from using PORE error +/// handlers. Therefore they don't require the 60 redundant bytes of error +/// handler entry points. They also only run trigger slot 0, and begin +/// execution with a BRAD D0, so the only thing we represent is a single BRAD +/// D0 instruction. + +static uint32_t* G_pore_flex_table = &G_pore_flex_entry0 - (PORE_ERROR_SLOTS * 3); + + +//////////////////////////////////////////////////////////////////////////// +// PoreQueue +//////////////////////////////////////////////////////////////////////////// + +/// Create (initialize) a PoreQueue +/// +/// \param queue An uninitialized of otherwise idle PoreQueue +/// +/// \param engine The identifier of a PORE engine associated with this queue. +/// +/// This API initializes the PoreQueue structure and also initializes the +/// underlying PORE hardware to run in the OCC environment. Neither the +/// branch table nor the error modes are specified here - those are considered +/// application-specific functions that are set up each time a job is run on +/// the engine. +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_OBJECT_PORE_QUEUE The \a queue was NULL (0). +/// +/// \retval -ASYNC_INVALID_ENGINE_PORE The \a engine is not a (valid) +/// PORE engine. + +int +pore_queue_create(PoreQueue *queue, int engine) +{ + pore_control_t control; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(queue == 0, ASYNC_INVALID_OBJECT_PORE_QUEUE); + SSX_ERROR_IF(!(engine & ASYNC_ENGINE_PORE), ASYNC_INVALID_ENGINE_PORE); + } + + async_queue_create(&(queue->queue), engine); + + switch (engine) { + + case ASYNC_ENGINE_PORE_GPE0: + queue->oci_base = PORE_GPE0_OCI_BASE; + queue->irq = PGP_IRQ_PORE_GPE0_COMPLETE; + queue->error_irq = PGP_IRQ_PORE_GPE0_ERROR; + queue->oci_master = OCI_MASTER_ID_PORE_GPE; + break; + + case ASYNC_ENGINE_PORE_GPE1: + queue->oci_base = PORE_GPE1_OCI_BASE; + queue->irq = PGP_IRQ_PORE_GPE1_COMPLETE; + queue->error_irq = PGP_IRQ_PORE_GPE1_ERROR; + queue->oci_master = OCI_MASTER_ID_PORE_GPE; + break; + + case ASYNC_ENGINE_PORE_SLW: + queue->oci_base = PORE_SLW_OCI_BASE; + queue->irq = PGP_IRQ_PORE_SW_COMPLETE; + queue->error_irq = PGP_IRQ_PORE_SW_ERROR; + queue->oci_master = OCI_MASTER_ID_PORE_SLW; + break; + + default: + SSX_PANIC(ASYNC_BUG_PORE_AT_CREATE); + } + + // PORE engine setup + // + // Force the PORE to stop and set it up for OCC control. Neither the + // breakpoint address nor the trap enable setting are modified in case + // they are being controlled from Simics or a hardware debugger ab initio. + // + // Register field settings: + // + // The scanclk ratio is not modified. + // The EXE-Trigger register is unlocked + // The freeze action is not modified + // Instruction parity is ignored + // The PIB parity checking setting is not modified + // The TRAP enable is not modified + // The breakpoint address is not modified + + control.value = in64(queue->oci_base + PORE_CONTROL_OFFSET); + + control.fields.start_stop = 1; + control.fields.lock_exe_trig= 0; + control.fields.check_parity = 0; + + out64(queue->oci_base + PORE_CONTROL_OFFSET, control.value); + + return 0; +} + + +// The interrupt handler for asynchronous PORE errors +// +// The PORE interrupts are disabled here, then cleared and re-enabled when the +// next job runs. This is to protect against "phantom" interrupts caused by +// PORE freeze-on-checkstop behavior. + +SSX_IRQ_FAST2FULL(pore_async_error_handler, pore_async_error_handler_full); + +void +pore_async_error_handler_full(void *arg, SsxIrqId irq, int priority) +{ + PoreQueue* queue = (PoreQueue*)arg; + + ssx_irq_disable(queue->irq); + ssx_irq_disable(queue->error_irq); + + async_error_handler((AsyncQueue *)arg, ASYNC_REQUEST_STATE_FAILED); +} + + +// The interrupt handler for asynchronous PORE requests +// +// The PORE interrupts are disabled here, then cleared and re-enabled when the +// next job runs. This is to protect against "phantom" interrupts caused by +// PORE freeze-on-checkstop behavior. +// +// Note that if the system checkstops and freezes the PORE we will get a +// normal completion interrupt. Therefore we have to check to see if the +// completion is associated with a freeze, and if so, fail the job. + +SSX_IRQ_FAST2FULL(pore_async_handler, pore_async_handler_full); + +void +pore_async_handler_full(void *arg, SsxIrqId irq, int priority) +{ + PoreQueue* queue = (PoreQueue*)arg; + pore_status_t status; + + status.value = in64(queue->oci_base + PORE_STATUS_OFFSET); + if (status.fields.freeze_action) { + + pore_async_error_handler_full(arg, irq, priority); + + } else { + + ssx_irq_disable(queue->irq); + ssx_irq_disable(queue->error_irq); + + async_handler((AsyncQueue *)arg); + } +} + + +//////////////////////////////////////////////////////////////////////////// +// PoreRequest +//////////////////////////////////////////////////////////////////////////// + +/// Create (initialize) the PoreRequest base class +/// +/// \param request An uninitialized or otherwise idle PoreRequest. +/// +/// \param queue An initialized PoreQueue +/// +/// \param table The PORE branch table to install prior to kicking off the +/// engine. All PoreFlex jobs use a common (stubbed) table. PoreFixed jobs +/// must supply a fully-formed table. +/// +/// \param error_mask The initial value of the PORE ERROR_MASK register to be +/// installed before kicking off the engine. +/// +/// \param entry_point The entry point address of the routine. For PoreFlex +/// this entry point will be non-0 and will be inserted into D0, as PoreFlex +/// jobs are kicked off by BRAD D0. For PoreFixed this parameter will be zero +/// and ignored. +/// +/// \param start_vector The TBAR start vector to execute. This will always be +/// 0 for PoreFlex. +/// +/// \param parameter The single 32-bit parameter to the PORE program. This +/// value is stored in the low-order part of the \c EXE_TRIGGER register +/// prior to initiating the PORE program. (This part of the \c EXE_TRIGGER +/// register is referred to as the 'Chiplet Select Mask' in PORE docs., as +/// this is the hardware usage for hardware-initiated PORE-SLW routines.) +/// +/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request +/// will be governed by a private watchdog timer that will cancel a queued job +/// or kill a running job if the hardware operation does not complete before +/// it times out. +/// +/// \param callback The callback to execute when the PORE program completes, +/// or NULL (0) to indicate no callback. +/// +/// \param arg The parameter to the callback routine; ignored if the \a +/// callback is NULL. +/// +/// \param options Options to control request priority and callback context. +/// +/// This routine has no way to know if the PoreRequest structure is currently +/// in use, so this API should only be called on uninitialized or otherwise +/// idle PoreRequest structures. +/// +/// \retval 0 Success +/// +/// \retval -ASYNC_INVALID_OBJECT_PORE_REQUEST The \a request was NULL (0) +/// or the \a queue was NULL (0) or not a PoreQueue. +/// +/// \retval -ASYNC_INVALID_ARGUMENT_PORE_REQUEST The \a start_vector is invalid or any of +/// the parameters that represent OCI addresses are not 4-byte aligned, , or +/// the \a table was null. +/// +/// See async_request_create() for other errors that may be returned by this +/// call. + +int +pore_request_create(PoreRequest *request, + PoreQueue *queue, + PoreBraia* table, + uint32_t error_mask, + uint32_t entry_point, + int start_vector, + uint32_t parameter, + SsxInterval timeout, + AsyncRequestCallback callback, + void *arg, + int options) +{ + AsyncQueue *async_queue = (AsyncQueue *)queue; + int rc; + pore_exe_trigger_t etr; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(!(async_queue->engine & ASYNC_ENGINE_PORE), + ASYNC_INVALID_OBJECT_PORE_REQUEST); + SSX_ERROR_IF((start_vector < 0) || + (start_vector >= PORE_TRIGGER_SLOTS) || + ((uint32_t) table % 4) || + (entry_point % 4) || + (table == 0), + ASYNC_INVALID_ARGUMENT_PORE_REQUEST); + } + + rc = async_request_create(&(request->request), + async_queue, + pore_run_method, + pore_error_method, + timeout, + callback, + arg, + options); + + if (!rc) { + request->table = table; + request->error_mask = error_mask; + request->entry_point = entry_point; + request->parameter = parameter; + etr.value = 0; + etr.fields.start_vector = start_vector; + request->exe_trigger = etr.words.high_order; + } + + return rc; +} + + +// Start a PoreRequest on a PORE +// +// \param async_request A PoreRequest upcast to an AsyncRequest. +// +// This is an internal API. At entry both the completion and error interrupts +// are disabled and may show status that needs to be cleared before they are +// re-enabled. +// +// This routine implements a simple procedure: +// +// - Check to make sure the PORE is not frozen due to a checkstop, and if so, +// collect FFDC and immediately fail the job. +// +// Otherwise: +// +// - Reset the PORE engine to clear up any error status that may remain from +// the last job . +// - Install the TBAR (Table Base Address Register) from the request as an OCI +// address +// - Set the EMR (Error Mask Register) from the request +// - Install the parameter (ETR[32:63]) +// - If the entry point is non-0 then this is a PoreFlex job that is kicked +// off by a BRAD D0, and the entry point is installed in D0 as a full OCI +// address. +// - Clear pending interrupt status +// - Hit ETR[0:31] to start the job. +// - Enable interrupts. +// +// If the PORE is frozen due to a system checkstop we fail the job immediately +// right here. Note that there is still a small window where the system may +// checkstop and the PORE may freeze after this check. Unfortunately the PORE +// design locks out register writes while frozen, and instead of reporting +// write access attempts as bus errors, silently ignores them and simply sets +// a FIR bit. Originally the "frozen" check was done last to shrink the +// window, however this practically guarantees these FIRs in a checkstopped +// system (which the FW team finds problematic), so the check was moved to the +// front of the procedure. (SW256621). +// +// Note that PORE interrupts remain masked unless the job starts successfully. + +int +pore_run_method(AsyncRequest *async_request) +{ + PoreQueue *queue = (PoreQueue*)(async_request->queue); + PoreRequest *request = (PoreRequest*)async_request; + pore_status_t status; + pore_reset_t reset; + uint32_t oci_base; + int rc; + + oci_base = queue->oci_base; + + status.value = in64(oci_base + PORE_STATUS_OFFSET); + if (status.fields.freeze_action) { + + pore_error_method(async_request); + async_request->completion_state = ASYNC_REQUEST_STATE_FAILED; + rc = -ASYNC_REQUEST_COMPLETE; + + } else { + + reset.value = 0; + reset.fields.fn_reset = 1; + out32(oci_base + PORE_RESET_OFFSET, reset.value); + + out32(oci_base + PORE_TABLE_BASE_ADDR_OFFSET, PORE_ADDRESS_SPACE_OCI); + out32(oci_base + PORE_TABLE_BASE_ADDR_OFFSET + 4, + (uint32_t)(request->table)); + out32(oci_base + PORE_ERROR_MASK_OFFSET, request->error_mask); + out32(oci_base + PORE_EXE_TRIGGER_OFFSET + 4, request->parameter); + + if (request->entry_point != 0) { + out32(oci_base + PORE_SCRATCH1_OFFSET, PORE_ADDRESS_SPACE_OCI); + out32(oci_base + PORE_SCRATCH1_OFFSET + 4, request->entry_point); + } + + ssx_irq_status_clear(queue->irq); + ssx_irq_status_clear(queue->error_irq); + + out32(oci_base + PORE_EXE_TRIGGER_OFFSET, request->exe_trigger); + + ssx_irq_enable(queue->irq); + ssx_irq_enable(queue->error_irq); + rc = 0; + } + + return rc; +} + + +// PORE FFDC collection +// +// \param async_request A PoreRequest upcast to an AsyncRequest +// +// This is an internal API, called from an interrupt context when a PORE +// engine signals an error interrupt. See the comments for PoreFfdc for a +// description of why this particular set of data is collected. +// +// PORE error handling procedure: +// +// - Collect FFDC from the PLB arbiter +// +// - Collect FFDC from the failing engine +// +// Currently all PORE errors are treated as recoverable + +/// \todo Consider analyzing the errors to determine if the error should be +/// considered fatal. + +int +pore_error_method(AsyncRequest *async_request) +{ + PoreQueue *queue = (PoreQueue*)(async_request->queue); + PoreRequest *request = (PoreRequest*)async_request; + uint32_t oci_base; + PoreFfdc* ffdc; + + oci_base = queue->oci_base; + ffdc = &(request->ffdc); + + oci_ffdc(&(ffdc->oci_ffdc), queue->oci_master); + + ffdc->debug[0] = in64(oci_base + PORE_DBG0_OFFSET); + ffdc->debug[1] = in64(oci_base + PORE_DBG1_OFFSET); + ffdc->address[0] = in32(oci_base + PORE_OCI_BASE_ADDRESS0_OFFSET + 4); + ffdc->address[1] = in32(oci_base + PORE_OCI_BASE_ADDRESS1_OFFSET + 4); + ffdc->ibuf[0] = in32(oci_base + PORE_IBUF_01_OFFSET); + ffdc->ibuf[1] = in32(oci_base + PORE_IBUF_01_OFFSET + 4); + ffdc->ibuf[2] = in32(oci_base + PORE_IBUF_2_OFFSET); + + return 0; +} + + +/// Create (initialize) a PoreBraia branch table entry +/// +/// \param instr A pointer to the BRAIA instruction to initialize. Use the +/// macros PORE_ERROR_BRANCH(table, n) and PORE_ENTRY_BRANCH(table, n) to +/// select one of 5 error branches or one of 16 entry point branches in a PORE +/// branch table. +/// +/// \param address The 32-bit OCI address of the error routine or entry point. +/// +/// This routine initializes the given entry of a PORE branch table with an +/// OCI-based BRAIA instruction, them flushes the entry from the D-Cache. + +// Note that we don't know the alignment of the jump table, so we need to +// flush both the first and last jump address to ensure that the BRAI is +// completely flushed. This assumes (correctly) that uint32_t are at least +// 4-byte aligned. + +void +pore_braia_create(PoreBraia* instr, uint32_t address) { + instr->word[0] = PORE_BRAI; + instr->word[1] = PORE_ADDRESS_SPACE_OCI; + instr->word[2] = address; + dcache_flush_line(&(instr->word[0])); + dcache_flush_line(&(instr->word[2])); +} + + +//////////////////////////////////////////////////////////////////////////// +// PoreFlex +//////////////////////////////////////////////////////////////////////////// + +/// Create (initialize) a flex-mode PORE request +/// +/// \param request An uninitialized or otherwise idle PoreFlex. +/// +/// \param queue A pointer to a PoreQueue +/// +/// \param entry_point The entry point of the PORE program. This must be a +/// 32-bit, 4-byte aligned byte address in OCI space. The PoreEntryPoint +/// typedef is provided to declare external PORE entry points. Note that an \a +/// entry_point of 0 is considered an error - although it \e is conceivably a +/// legal OCI address in mainstore via the PBA. +/// +/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request +/// will be governed by a private watchdog timer that will cancel a queued job +/// or kill a running job if the hardware operation does not complete before +/// it times out. +/// +/// \param parameter The single 32-bit parameter to the PORE program. This +/// value is stored in the high-order part of the \c EXE_TRIGGER register +/// prior to initiating the PORE program. (This part of the \c EXE_TRIGGER +/// register is referred to as the 'Chiplet Select Mask' in PORE docs., as +/// this is the hardware usage for hardware-initiated PORE-SLW routines.) +/// +/// \param callback The callback to execute when the PORE program completes, +/// or NULL (0) to indicate no callback. +/// +/// \param arg The parameter to the callback routine; ignored if the \a +/// callback is NULL. +/// +/// \param options Options to control request priority and callback context. +/// +/// This routine has no way to know if the PoreFlex structure is currently +/// in use, so this API should only be called on uninitialized or +/// otherwise idle PoreFlex structures. +/// +/// \retval 0 Success +/// +/// See pore_request_create() for error return codes that may be returned by +/// this call. + +int +pore_flex_create(PoreFlex *request, + PoreQueue *queue, + PoreEntryPoint entry_point, + uint32_t parameter, + SsxInterval timeout, + AsyncRequestCallback callback, + void *arg, + int options) +{ + uint32_t emr; + + // PoreFlex jobs run w/o error handlers, and ignore sleeping cores. All + // errors are signalled on both error outputs of all PORE engines. + + emr = (PORE_ERROR_MASK_ENABLE_ERR_OUTPUT0 | + PORE_ERROR_MASK_ENABLE_ERR_OUTPUT1 | + PORE_ERROR_MASK_ENABLE_ERR_OUTPUT2 | + PORE_ERROR_MASK_ENABLE_ERR_OUTPUT3 | + PORE_ERROR_MASK_ENABLE_ERR_OUTPUT4 | + PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT0 | + PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT1 | + PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT2 | + PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT3 | + PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT4 | + PORE_ERROR_MASK_STOP_EXE_ON_ERROR0 | + PORE_ERROR_MASK_STOP_EXE_ON_ERROR1 | + PORE_ERROR_MASK_STOP_EXE_ON_ERROR2 | + PORE_ERROR_MASK_STOP_EXE_ON_ERROR3 | + PORE_ERROR_MASK_STOP_EXE_ON_ERROR4) >> 32; + + return pore_request_create((PoreRequest*)request, + queue, + (PoreBraia*)G_pore_flex_table, + emr, + (uint32_t)entry_point, + 0, + parameter, + timeout, + callback, + arg, + options); +} + + +//////////////////////////////////////////////////////////////////////////// +// PoreFixed +//////////////////////////////////////////////////////////////////////////// + +/// Create (initialize) a fixed-mode PORE request +/// +/// \param request An uninitialized or otherwise idle PoreFixed request. +/// +/// \param queue A PoreQueue capable of running fixed requests. +/// +/// \param table A PORE branch table containing all of the error handler and +/// entry point assignments required for the request. +/// +/// \param error_mask A value that will be loaded into the high-order 32-bits +/// of the PORE Error Mask Register to control error behavior. +/// +/// \param start_vector The branch table slot reserved for this request. +/// +/// \param parameter The single 32-bit parameter to the PORE program. This +/// value is stored in the high-order part of the \c EXE_TRIGGER register +/// prior to initiating the PORE program. (This part of the \c EXE_TRIGGER +/// register is referred to as the 'Chiplet Select Mask' in PORE docs., as +/// this is the hardware usage for hardware-initiated PORE-SLW routines.) +/// +/// \param timeout If not specified as SSX_WAIT_FOREVER, then this request +/// will be governed by a private watchdog timer that will cancel a queued job +/// or kill a running job if the hardware operation does not complete before +/// it times out. +/// +/// \param callback The callback to execute when the PORE program completes, +/// or NULL (0) to indicate no callback. +/// +/// \param arg The parameter to the callback routine; ignored if the \a +/// callback is NULL. +/// +/// \param options Options to control request priority and callback context. +/// +/// This routine has no way to know if the PoreFixed structure is currently +/// in use, so this API should only be called on uninitialized or +/// otherwise idle PoreFlex structures. +/// +/// \retval 0 Success +/// +/// See pore_request_create() for error return codes that may be returned by +/// this call. + +int +pore_fixed_create(PoreFixed *request, + PoreQueue *queue, + PoreBraia* table, + uint32_t error_mask, + int start_vector, + uint32_t parameter, + SsxInterval timeout, + AsyncRequestCallback callback, + void *arg, + int options) +{ + return pore_request_create((PoreRequest*)request, + queue, + table, + error_mask, + 0, + start_vector, + parameter, + timeout, + callback, + arg, + options); +} + + +//////////////////////////////////////////////////////////////////////////// +// Initialization +//////////////////////////////////////////////////////////////////////////// + +// Due to the fact that PORE signals a "complete" interrupt on a freeze event +// (i.e., a checkstop, even if PORE is not running), we can not enable PORE +// interrupts globally. They need to be carefully managed to avoid "phantom +// interrupt" panics from async_handler(). + +void +async_pore_initialize(PoreQueue *queue,int engine) +{ + pore_queue_create(queue, engine); + async_edge_handler_setup(pore_async_handler, + (void *)queue, + queue->irq, SSX_CRITICAL); + async_edge_handler_setup(pore_async_error_handler, + (void *)queue, + queue->error_irq, SSX_CRITICAL); +} + + + diff --git a/src/ssx/pgp/pgp_cache.S b/src/ssx/pgp/pgp_cache.S new file mode 100755 index 0000000..4208f59 --- /dev/null +++ b/src/ssx/pgp/pgp_cache.S @@ -0,0 +1,99 @@ +// $Id: pgp_cache.S,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_cache.S,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_cache.S +/// \brief Cache-management specific to PGP + +#include "ssx.h" + +/// \fn void dcache_flush_all() +/// \brief Flush the entire D-Cache by 0-filling and invalidating +/// +/// This API is necessary whenever it is required to change data cacheability +/// after boot. This API operates in an SSX_SUPERCRITICAL critical section. +/// This API always issues a sync() after the flush. +/// +/// This API runs with data translation disabled. This is necessary for +/// correctness, and also obviates the need to check whether a cache entry is +/// valid before flushing the entry. +/// +/// This algorithm works by filling the cache with 0s to displace any dirty +/// lines. Then the cache is invalidated. In PgP the first 16 KB of the +/// 0x80000000 address range are used as the zero-fill range. This memory is +/// not mapped on the OCI so these lines must never escape the D-cache. +/// +/// Note: Our Simics model includes this 16K memory area since Simics does not +/// default to having a cache. Since we run PgP with the MMU enabled and we +/// don't MMU-map this area, memory addressing bugs should not be able to slip +/// through. +#ifdef DOXYGEN_ONLY +void dcache_flush_all(); +#endif +/// \cond + + .global_function dcache_flush_all +dcache_flush_all: + + ## %r3 used as scratch throughout + + ## %r11 holds the original DCCR throughout + ## %r12 holds the original MSR throughout + + ## Enter a super-critical section and go to real mode + + _ssx_critical_section_enter SSX_SUPERCRITICAL, %r12, %r3 + + mfmsr %r3 + _clrbit %r3, %r3, MSR_DR_BIT + mtmsr %r3 + isync + + ## Save the DCCR, and make 0x80000000 cacheable. This is necessary for + ## DCBZ to work. + + mfdccr %r11 + _liwa %r3, PGP_FLUSH_ZERO_DCCR + or %r3, %r3, %r11 + mtdccr %r3 + isync + + ## Fill the cache with 0, displacing any dirty lines + + li %r3, DCACHE_LINES + mtctr %r3 + _liwa %r3, PGP_FLUSH_ZERO_ADDRESS +1: + dcbz %r0, %r3 + addi %r3, %r3, CACHE_LINE_SIZE + bdnz 1b + + sync + + ## Now invalidate the cache + + li %r3, DCACHE_LINES + mtctr %r3 + _liwa %r3, PGP_FLUSH_ZERO_ADDRESS +1: + dcbi %r0, %r3 + addi %r3, %r3, CACHE_LINE_SIZE + bdnz 1b + + ## Restore the DCCR and MSR and return + + mtdccr %r11 + isync + + _ssx_critical_section_exit %r12 + + blr + + .epilogue dcache_flush_all + +/// \endcond + diff --git a/src/ssx/pgp/pgp_centaur.c b/src/ssx/pgp/pgp_centaur.c new file mode 100644 index 0000000..a47600a --- /dev/null +++ b/src/ssx/pgp/pgp_centaur.c @@ -0,0 +1,597 @@ +// $Id: pgp_centaur.c,v 1.2 2013/12/13 23:01:15 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_centaur.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_centaur.c +/// \brief Support for Centaur access and configuration from OCC. +/// +/// Generic PBA generated PowerBus Address in pictures and words: +/// +/// \code +/// +/// 1 2 3 4 5 6 +/// 0123456789012345678901234567890123456789012345678901234567890123 +/// | | | | | | | | | | | | | | | +/// +/// ..............B-------BX------------XO-----OA------------------A +/// +/// .: Unused +/// B: Direct from PBA BAR, bits 14:22 +/// X: If PBA BAR MASK 23:36 == 0, then PBA BAR 23:36 +/// Else Extended Address 0:13 +/// O: If PBA BAR MASK 37:43 == 0, then PBA BAR 37:43 +/// Else OCI Address 5:11 +/// A: OCI Address 12:31 +/// +/// \endcode +/// +/// The OCI address always selects the low-order 20 bits of the PowerBus +/// address, i.e., the window size is always a multiple of 1MB. The PBA BAR +/// mask allows up to a 128MB window into main memory without using the +/// extended address. The extended address allows OCC to address up to 2^41 +/// bytes by manipulating the extended address, assuming PHYP sets up the mask +/// correctly. +/// +/// +/// Centaur in-band SCOM, sensor cache and SYNC addressing in pictures and words: +/// +/// \code +/// +/// 1 2 3 4 5 6 +/// 0123456789012345678901234567890123456789012345678901234567890123 +/// | | | | | | | | | | | | | | | +/// +/// ..............B-------BX------------XO-----OA------------------A - See Above +/// ..............M-----------M10S------------------------------S000 - SCOM +/// ..............M-----------M1100000000000000000000000000000000000 - Sensor cache +/// ..............M-----------M1110000000000000000000000000000000000 - Sync +/// +/// .: Unused +/// M: The base address of the Centaur, taken from the MCS MCFGPR. +/// O: 1 Signifies that this access comes from the OCC. +/// S: The 32-bit SCOM address +/// 0: Zero +/// +/// \endcode +/// +/// In order to access the Centaur for in-band SCOM, the PBA BAR MASK must +/// extend at least from bit 29 down to bit 43, in order to allow the OCC to +/// generate these addresses. In practice the mask must allow all configured +/// Centaur to be accessed. This means that all Centaur in-band address bits +/// not controllable by OCC through the mask must be equal. +/// +/// Note that the SCOM address must be split between the extended address and +/// the OCI address. +/// +/// We assume (and verify) that MCMODE0(36) will always be set which means +/// that bit 27 is a flag indicating whether an access comes from FSP or +/// OCC. All OCC (GPE) accesses set this flag to 1. + +#include "ssx.h" +#include "gpe_scom.h" + +#if defined(VERIFICATION) || defined(LAB_VALIDATION) +#define PRINTD(...) printk(__VA_ARGS__) +#else +#define PRINTD(...) +#endif + +CentaurConfiguration G_centaurConfiguration +SECTION_ATTRIBUTE(".noncacheable_ro") = {.configRc = CENTAUR_NOT_CONFIGURED}; + +const uint16_t _pgp_mcs_offset[PGP_NMCS] = { + 0x0800, 0x0880, 0x0900, 0x0980, 0x0c00, 0x0c80, 0x0d00, 0x0d80 +}; + + +// All GpeScomParms structures are required to be noncacheable, so we have to +// allocate a static instance rather than using the stack. For simplicity the +// single-entry scomList_t required to collect the Centaur device IDs is +// allocated statically as well. + +static GpeScomParms S_parms SECTION_ATTRIBUTE(".noncacheable") = {0}; +static scomList_t S_scomList SECTION_ATTRIBUTE(".noncacheable") = {{{0}}}; + +int +_centaur_configuration_create(int i_bar, int i_slave, int i_setup) +{ + CentaurConfiguration config; + int i, designatedSync, diffInit; + int64_t rc; /* Must be copied to global struct. */ + mcfgpr_t mcfgpr; + mcsmode0_t mcsmode0; + pba_slvctln_t slvctl; + uint64_t diffMask, addrAccum, bar, mask, base; + PoreFlex request; + + // Start by clearing the local structure and setting the error flag. + memset(&config, 0, sizeof(config)); + config.configRc = CENTAUR_NOT_CONFIGURED; + + designatedSync = -1; + + do { + // Basic consistency checks + + if ((i_bar < 0) || (i_bar >= PBA_BARS) || + (i_slave < 0) || (i_slave >= PBA_SLAVES)) { + + rc = CENTAUR_INVALID_ARGUMENT; + break; + } + + + // Create the setups for the GPE procedures. The 'dataParms' are the + // setup for accessing the Centaur sensor cache. The 'scomParms' are + // the setup for accessing Centaur SCOMs. + + rc = gpe_pba_parms_create(&(config.dataParms), + PBA_SLAVE_PORE_GPE, + PBA_WRITE_TTYPE_CI_PR_W, + PBA_WRITE_TTYPE_DC, + PBA_READ_TTYPE_CL_RD_NC); + if (rc) { + rc = CENTAUR_DATA_SETUP_ERROR; + break; + } + + rc = gpe_pba_parms_create(&(config.scomParms), + PBA_SLAVE_PORE_GPE, + PBA_WRITE_TTYPE_CI_PR_W, + PBA_WRITE_TTYPE_DC, + PBA_READ_TTYPE_CI_PR_RD); + if (rc) { + rc = CENTAUR_SCOM_SETUP_ERROR; + break; + } + + + // Go into each MCS on the chip, and for all enabled MCS get a couple + // of SCOMs and check configuration items for correctness. If any of + // the Centaur are configured, exactly one of the MCS must be + // designated to receive the SYNC commands. + + // Note that the code uniformly treats SCOM failures of the MCFGPR + // registers as an unconfigured Centaur. This works both for Murano, + // which only defines the final 4 MCS, as well as for our VBU models + // where some of the "valid" MCS are not in the simulation models. + + for (i = 0; i < PGP_NCENTAUR; i++) { + + rc = _getscom(MCS_ADDRESS(MCFGPR, i), &(mcfgpr.value), + SCOM_TIMEOUT); + if (rc) { + rc = 0; + config.baseAddress[i] = 0; + continue; + } + + if (!mcfgpr.fields.mcfgprq_valid) continue; + + rc = _getscom(MCS_ADDRESS(MCSMODE0, i), &(mcsmode0.value), + SCOM_TIMEOUT); + if (rc) { + PRINTD("Unexpected rc = 0x%08x SCOMing MCSMODE0(%d)\n", + (uint32_t)rc, i); + rc = CENTAUR_MCSMODE0_SCOM_FAILURE; + break; + } + + + // We require that the MCFGRP_19_IS_HO_BIT be set in the mode + // register. We do not support the option of this bit not being + // set, and all of our procedures will set bit 19 of the PowerBus + // address to indicate that OCC is making the access. + + if (!mcsmode0.fields.mcfgrp_19_is_ho_bit) { + + PRINTD("MCSMODE0(%d).mcfgrp_19_is_ho_bit == 0\n", i); + rc = CENTAUR_MCSMODE0_19_FAILURE; + break; + } + + + // The 14-bit base-address is moved to begin at bit 14 in the + // 64-bit PowerBus address. The low-order bit of this address (bit + // 19 mentioned above which is bit 27 as an address bit) must be 0 + // - otherwise there is confusion over who's controlling this + // bit. + + config.baseAddress[i] = + ((uint64_t)(mcfgpr.fields.mcfgprq_base_address)) << + (64 - 14 - 14); + + if (config.baseAddress[i] & 0x0000001000000000ull) { + + PRINTD("Centaur base address %d has bit 27 set\n", i); + rc = CENTAUR_ADDRESS_27_FAILURE; + break; + } + + + // If this MCS is configured to be the designated SYNC unit, it + // must be the only one. + + if (mcsmode0.fields.enable_centaur_sync) { + + if (designatedSync > 0) { + + PRINTD("Both MCS %d and %d are designated " + "for Centaur Sync\n", + designatedSync, i); + rc = CENTAUR_MULTIPLE_DESIGNATED_SYNC; + break; + + } else { + + designatedSync = i; + } + } + + + // Add the Centaur to the configuration + + config.config |= (CHIP_CONFIG_MCS(i) | CHIP_CONFIG_CENTAUR(i)); + } + + if (rc) break; + + + // If Centaur are configured, make sure at least one of the MCS will + // handle the SYNC. If so, convert its base address into an address + // for issuing SYNC commands by setting bits 27 (OCC) 28 and 29 + // (Sync), then insert this address into the extended address field of + // a PBA slave control register image. gsc_scom_centaur() then merges + // this extended address into the PBA slave control register (which + // has been set up for Centaur SCOM) to do the SYNC. + + // In the override mode (i_setup > 1) we tag the first valid MCS + // to recieve the sync if the firmware has not set it up correctly. + + if (config.config) { + + if (designatedSync < 0) { + + if (i_setup <= 1) { + + PRINTD("No MCS is designated for Centaur SYNC\n"); + rc = CENTAUR_NO_DESIGNATED_SYNC; + break; + + } else { + + designatedSync = + cntlz32(left_justify_mcs_config(config.config)); + + rc = _getscom(MCS_ADDRESS(MCSMODE0, designatedSync), + &(mcsmode0.value), + SCOM_TIMEOUT); + if (rc) { + PRINTD("Unexpected rc = 0x%08x SCOMing MCSMODE0(%d)\n", + (uint32_t)rc, designatedSync); + rc = CENTAUR_MCSMODE0_SCOM_FAILURE; + break; + } + + mcsmode0.fields.enable_centaur_sync = 1; + + rc = _putscom(MCS_ADDRESS(MCSMODE0, designatedSync), + mcsmode0.value, + SCOM_TIMEOUT); + if (rc) { + PRINTD("Unexpected rc = 0x%08x SCOMing MCSMODE0(%d)\n", + (uint32_t)rc, designatedSync); + rc = CENTAUR_MCSMODE0_SCOM_FAILURE; + break; + } + } + } + + base = config.baseAddress[designatedSync] | 0x0000001c00000000ull; + + slvctl.value = 0; + slvctl.fields.extaddr = (base & 0x000001fff8000000ull) >> 27; + + config.syncSlaveControl = slvctl.value; + } + + + // At this point we have one or more enabled MCS and they pass the + // initial configuration sniff test. We can now implement the option + // to configure the PBA BAR and BAR MASK correctly to allow access to + // these Centaur. We do this by computing the minimum BAR mask that + // covers all of the Centaur base addresses. This is done by + // accumulating a difference mask of the base addresses and finding + // the first set bit in the mask. + // + // Note that we do the configuration here on demand, but always do the + // correctness checking as the next step. + + if (i_setup && (config.config != 0)) { + + diffInit = 0; + diffMask = 0; /* GCC happiness */ + addrAccum = 0; /* GCC happiness */ + + for (i = 0; i < PGP_NCENTAUR; i++) { + + if (config.baseAddress[i] != 0) { + + if (!diffInit) { + + diffInit = 1; + diffMask = 0; + addrAccum = config.baseAddress[i]; + + } else { + + diffMask |= + (config.baseAddress[i] ^ addrAccum); + addrAccum |= config.baseAddress[i]; + } + + if (0) { + + // Debug + + printk("i:%d baseAddress: 0x%016llx " + "diffMask: 0x%016llx, addrAccum: 0x%016llx\n", + i, config.baseAddress[i], diffMask, addrAccum); + } + } + } + + // The mask must cover all differences - and must also have at + // least bit 27 set. The mask register contains only the mask. The + // BAR is set to the accumulated address outside of the mask. The + // BAR also contains a scope field which defaults to 0 (Nodal + // Scope) for Centaur inband access. + + diffMask |= 0x0000001000000000ull; + mask = + ((1ull << (64 - cntlz64(diffMask))) - 1) & + PBA_BARMSKN_MASK_MASK; + + rc = _putscom(PBA_BARMSKN(i_bar), mask, SCOM_TIMEOUT); + if (rc) { + PRINTD("Unexpected rc = 0x%08x SCOMing PBA_BARMSKN(%d)\n", + (uint32_t)rc, i_bar); + rc = CENTAUR_BARMSKN_PUTSCOM_FAILURE; + break; + } + + rc = _putscom(PBA_BARN(i_bar), addrAccum & ~mask, SCOM_TIMEOUT); + if (rc) { + PRINTD("Unexpected rc = 0x%08x SCOMing PBA_BARN(%d)\n", + (uint32_t)rc, i_bar); + rc = CENTAUR_BARN_PUTSCOM_FAILURE; + break; + } + } + + + // Do an independent check that every Centaur base address + // can be generated by the combination of the current BAR and + // BAR Mask, along with the initial requirement that the mask must + // include at least bits 27:43. + + if (config.config != 0) { + + rc = _getscom(PBA_BARN(i_bar), &bar, SCOM_TIMEOUT); + if (rc) { + PRINTD("Unexpected rc = 0x%08x SCOMing PBA_BARN(%d)\n", + (uint32_t)rc, i_bar); + rc = CENTAUR_BARN_GETSCOM_FAILURE; + break; + } + + rc = _getscom(PBA_BARMSKN(i_bar), &mask, SCOM_TIMEOUT); + + if (rc) { + PRINTD("Unexpected rc = 0x%08x SCOMing PBA_BARMSKN(%d)\n", + (uint32_t)rc, i_bar); + rc = CENTAUR_BARMSKN_GETSCOM_FAILURE; + break; + } + + bar = bar & PBA_BARN_ADDR_MASK; + mask = mask & PBA_BARMSKN_MASK_MASK; + + if ((mask & 0x0000001ffff00000ull) != 0x0000001ffff00000ull) { + + PRINTD("PBA BAR mask (%d) does not cover bits 27:43\n", i_bar); + rc = CENTAUR_MASK_ERROR; + break; + } + + for (i = 0; i < PGP_NCENTAUR; i++) { + + if (config.baseAddress[i] != 0) { + + if ((config.baseAddress[i] & ~mask) != + (bar & ~mask)) { + + PRINTD("BAR/Mask (%d) error for MCS/Centaur %d\n" + " base = 0x%016llx\n" + " bar = 0x%016llx\n" + " mask = 0x%016llx\n", + + i_bar, i, config.baseAddress[i], bar, mask); + rc = CENTAUR_BAR_MASK_ERROR; + break; + } + } + } + + if (rc) break; + } + + + // At this point the structure is initialized well-enough that it can + // be used by gpe_scom_centaur(). We run gpe_scom_centaur() to collect + // the CFAM ids of the chips. Prior to this we copy our local copy + // into the global read-only data structure. (Note that GPE can DMA + // under the OCC TLB memory protection.) In order for + // gpe_scom_centaur() to run the global configuration must be valid + // (configRc == 0) - so we provisionally mark it valid (and will + // invalidate it later if errors occur here). + + // Note however that if no Centaur are present then we're already + // done. + + // It's assumed that this procedure is being run before threads have + // started, therefore we must poll for completion of the GPE program. + // Assuming no contention for GPE1 this procedure should take a few + // microseconds at most to complete. + + if (0) { + + // Debug for Simics - only enable MCS 5 + + config.baseAddress[0] = + config.baseAddress[1] = + config.baseAddress[2] = + config.baseAddress[3] = + config.baseAddress[4] = + config.baseAddress[6] = + config.baseAddress[7] = 0; + } + + + config.configRc = 0; + memcpy_real(&G_centaurConfiguration, &config, sizeof(config)); + + if (config.config == 0) break; + + S_scomList.scom = CENTAUR_DEVICE_ID; + S_scomList.commandType = GPE_SCOM_READ_VECTOR; + S_scomList.pData = G_centaurConfiguration.deviceId; + + S_parms.scomList = CAST_POINTER(uint64_t, &S_scomList); + S_parms.entries = 1; + S_parms.options = 0; + + pore_flex_create(&request, + &G_pore_gpe1_queue, + gpe_scom_centaur, + (uint32_t)(&S_parms), + SSX_MILLISECONDS(10), /* Timeout */ + 0, 0, 0); + + rc = pore_flex_schedule(&request); + + if (rc) break; + + while (!async_request_is_idle((AsyncRequest*)(&request))); + + if (!async_request_completed((AsyncRequest*)(&request)) || + (S_parms.rc != 0)) { + + PRINTD("gpe_scom_centaur() for CENTAUR_DEVICE_ID failed:\n" + " Async state = 0x%02x\n" + " gpe_scom_centaur() rc = %u\n" + " gpe_scom_centaur() errorIndex = %d\n", + ((AsyncRequest*)(&request))->state, + S_parms.rc, S_parms.errorIndex); + + rc = CENTAUR_READ_TPC_ID_FAILURE; + } + + if (0) { + + // Debug + + slvctl.value = G_gsc_lastSlaveControl; + + PRINTD("centaur_configuration_create:Debug\n" + " Last SCOM (PowerBus) address = 0x%016llx\n" + " Last Slave Control = 0x%016llx\n" + " Extended Address (positioned) = 0x%016llx\n" + " Last OCI Address = 0x%016llx\n", + G_gsc_lastScomAddress, + G_gsc_lastSlaveControl, + (unsigned long long)(slvctl.fields.extaddr) << + (64 - 23 - 14), + G_gsc_lastOciAddress); + } + + } while (0); + + // Copy the final RC into the global structure and done. + + memcpy_real(&(G_centaurConfiguration.configRc), &rc, sizeof(rc)); + + return rc; +} + + +// For now we have to handle configuring the PBA BAR and mask, and designating +// a SYNC if the firmware forgot to. + +int +centaur_configuration_create(void) +{ + return _centaur_configuration_create(PBA_BAR_CENTAUR, + PBA_SLAVE_PORE_GPE, + 2); +} + + +uint32_t mb_id(int i_mb) +{ + uint32_t rv; + centaur_device_id_t id; + + if ((i_mb < 0) || (i_mb >= PGP_NCENTAUR) || + (G_centaurConfiguration.configRc != 0)) { + + rv = (uint32_t)-1; + + } else { + + id.value = G_centaurConfiguration.deviceId[i_mb]; + rv = id.fields.cfam_id; + } + + return rv; +} + + +uint8_t mb_chip_type(int i_mb) +{ + uint8_t rv; + cfam_id_t id; + + if ((id.value = mb_id(i_mb)) == -1) { + + rv = (uint8_t)-1; + + } else { + + rv = id.chipType; + } + + return rv; +} + + +uint8_t mb_ec_level(int i_mb) +{ + uint8_t rv; + cfam_id_t id; + + if ((id.value = mb_id(i_mb)) == -1) { + + rv = (uint8_t)-1; + + } else { + + rv = (id.majorEc << 4) | id.minorEc; + } + + return rv; +} diff --git a/src/ssx/pgp/pgp_centaur.h b/src/ssx/pgp/pgp_centaur.h new file mode 100644 index 0000000..8c2ccee --- /dev/null +++ b/src/ssx/pgp/pgp_centaur.h @@ -0,0 +1,254 @@ +#ifndef __PGP_CENTAUR_H__ +#define __PGP_CENTAUR_H__ + +// $Id: pgp_centaur.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_centaur.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_centaur.h +/// \brief Support for Centaur access and configuration from OCC. + +#include "gpe_pba.h" + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + +/// Compute the address of an MCS unit register from an index +/// +/// The MCS units have a bizarre PIB addressing scheme. This macro generates +/// MCS unit PIB addresses from a register name (w/o unit/index prefix), +/// assuming a valid index in the range 0:7. In the big sceheme of things it +/// probably saves space and time to do this with a table lookup rather than +/// generating the code to compute the address modification. (If we ever need +/// these in assembler code we'll have to implement a macro). + +#define MCS_ADDRESS(reg, index) (MCS0_##reg | _pgp_mcs_offset[index]) + +extern const uint16_t _pgp_mcs_offset[PGP_NMCS]; + + +/// A description of the current Centaur configuration +/// +/// \note Because this structure is read by the GPE engine it is strongly +/// recommended to allocate instances of this structure in non-cacheable data +/// sections, with the caveat that data structures assigned to non-default +/// data sections must always be initialized. For example: +/// +/// \code +/// +/// CentaurConfiguration G_centaurConfiguration +/// SECTION_ATTRIBUTE(".noncacheable_ro") = +/// {.configRc = CENTAUR_NOT_CONFIGURED}; +/// +/// \endcode + +typedef struct { + + /// Centaur base addresses for in-band operations + /// + /// These base addresses are used by GPE programs so it is most convenient + /// to store the entire 64 bits, even though only bits 23:26 of the base + /// address can be manipulated through the PBA BARs and BAR masks. A 0 + /// value indicates an unconfigured Centaur (MCS). + uint64_t baseAddress[PGP_NCENTAUR]; + + /// Contents of Centaur device id registers + /// + /// These are the device ID SCOMs (0x000f000f) read from configured + /// Centaur during initialization. A 0 value indicates an unconfigured + /// Centaur. These values are deconstructed by the memory buffer (mb) + /// APIs mb_id(), mb_chip_type() and mb_ec_level(). + uint64_t deviceId[PGP_NCENTAUR]; + + /// A "chip configuration" bit mask denoting valid Centaur + /// + /// It shoud always be true that a bit denoting a configured Centaur is + /// associated with a non-0 \a baseAddress and vice-versa. + ChipConfig config; + + /// The image of the PBA slave control register to use for the SYNC command + /// + /// The PowerBus address used to accomplish a Centaur SYNC is + /// constant. To simplify the procedures the PBA slave control register + /// (containing the extended address portion of the address) is + /// pre-computed and stored here. + /// + /// \note One and Only one of the MCS units can be targeted with SYNC + /// commands. The design includes a private bus connecting all MCS on the + /// chip that allows this "SYNC master" to broadcast the SYNC to all other + /// MCS on the chip. + uint64_t syncSlaveControl; + + /// A GpePbaParms parameter block for gpe_mem_data() + /// + /// This parameter block is set up in advance and used by the GPE + /// procedure gpe_mem_data(). Given the complexity of accessing Centaur + /// sensors and SCOM through the PBA it is simpler to set these up ahead + /// of time and simply have the GPE procedures access preconfigured global + /// data. The \a dataParms and \a scomParms members are distinguished by + /// the different way the PBA slave needs to be configured to access + /// either the Centaur sensor cache or Centaur SCOMs. + GpePbaParms dataParms; + + /// A GpePbaParms parameter block for gpe_scom_centaur(). + GpePbaParms scomParms; + + /// The final return code from centaur_configuration_create(). + /// + /// If initialization fails then this value can be used to diagnose what + /// happend. This field should be statically initialized to a non-0 value + /// (CENTAUR_NOT_CONFIGURED) and can then be checked against 0 to + /// determine if the structure has been correctly initialized. + int64_t configRc; + +} CentaurConfiguration; + +/// The global CentaurConfiguration created during initialization +extern CentaurConfiguration G_centaurConfiguration; + +#else // __ASSEMBLER__ + + .set CENTAUR_CONFIGURATION_BASE_ADDRESS, 0x0 + + .set CENTAUR_CONFIGURATION_DEVICE_ID, \ + (CENTAUR_CONFIGURATION_BASE_ADDRESS + (8 * PGP_NCENTAUR)) + + .set CENTAUR_CONFIGURATION_CONFIG, \ + (CENTAUR_CONFIGURATION_DEVICE_ID + (8 * PGP_NCENTAUR)) + + .set CENTAUR_CONFIGURATION_SYNC_SLAVE_CONTROL, \ + (CENTAUR_CONFIGURATION_CONFIG + 8) + + .set CENTAUR_CONFIGURATION_DATA_PARMS, \ + (CENTAUR_CONFIGURATION_SYNC_SLAVE_CONTROL + 8) + + .set CENTAUR_CONFIGURATION_SCOM_PARMS, \ + (CENTAUR_CONFIGURATION_DATA_PARMS + SIZEOF_GPEPBAPARMS) + + .set CENTAUR_CONFIGURATION_CONFIG_RC, \ + (CENTAUR_CONFIGURATION_SCOM_PARMS + SIZEOF_GPEPBAPARMS) + + .set SIZEOF_CENTAUR_CONFIGURATION, \ + (CENTAUR_CONFIGURATION_CONFIG_RC + 8) + +#endif // __ASSEMBLER__ + + +#ifndef __ASSEMBLER__ + +/// Error return codes set/returned by centaur_configuration_create() + +enum CentaurConfigurationCreateRc{ + + CENTAUR_INVALID_ARGUMENT = 0x007ccc01, + CENTAUR_MCSMODE0_SCOM_FAILURE = 0x007ccc02, + CENTAUR_MCSMODE0_19_FAILURE = 0x007ccc03, + CENTAUR_ADDRESS_27_FAILURE = 0x007ccc04, + CENTAUR_MULTIPLE_DESIGNATED_SYNC = 0x007ccc05, + CENTAUR_NO_DESIGNATED_SYNC = 0x007ccc06, + CENTAUR_BAR_MASK_ERROR = 0x007ccc07, + CENTAUR_CONFIGURATION_FAILED = 0x007ccc08, + CENTAUR_DATA_SETUP_ERROR = 0x007ccc09, + CENTAUR_SCOM_SETUP_ERROR = 0x007ccc0a, + CENTAUR_NOT_CONFIGURED = 0x007ccc0b, + CENTAUR_MASK_ERROR = 0x007ccc0c, + CENTAUR_READ_TPC_ID_FAILURE = 0x007ccc0d, + CENTAUR_BARMSKN_PUTSCOM_FAILURE = 0x007ccc0e, + CENTAUR_BARN_PUTSCOM_FAILURE = 0x007ccc0f, + CENTAUR_BARMSKN_GETSCOM_FAILURE = 0x007ccc10, + CENTAUR_BARN_GETSCOM_FAILURE = 0x007ccc11, +}; + + +/// Create (initialize) G_centaurConfiguration +/// +/// G_centaurConfiguration is a global structure used by GPE procedures to +/// access Centaur, and the mb_*() APIs to return CFAM-id type information +/// about the Centaurs. +/// +/// To complete Centaur configuration requires running the GPE program +/// gpe_scom_centaur() on PORE-GPE1 to collect the TPC device Ids of the +/// Centaur chips. This means that the "async" drivers must be set up prior to +/// the call. We assume this API will be called before threads have started, +/// thus it will poll the async request for completion. Assuming no other GPE +/// programs are scheduled this should take a few microseconds at most. +/// +/// \returns Either 0 for success or an element of the +/// CentaurConfigurationCreateRc enumeration. +int +centaur_configuration_create(void); + + +/// Create (initialize) G_centaurConfiguration (Internal API) +/// +/// \param[in] i_bar The index of the PBA BAR reserved for access to +/// Centaur. This will normally be passed as the constant PBA_BAR_CENTAUR but +/// is allowed to be variable for special cases. +/// +/// \param[in] i_slave The index of the PBA slave reserved for access from the +/// GPE complex. This will normally be passed as the constant +/// PBA_SLAVE_PORE_GPE but is allowed to be variable for special cases. +/// +/// \param[in] i_setup If non-0, then this procedure will set up the PBA BAR +/// correctly for access to Centaur. If > 1, then the procedure will also +/// designate an MCS to recieve the Centaur SYNC if the firmware failed to do +/// so. +/// +/// This API must be run early in the initialization flow, likely before the +/// real-time loop is activated. The API first scans the MBS configuration for +/// correctness and (optionally) sets up the PBA BAR and mask for access to +/// Centaur. The API then runs the gpe_scom_centaur() procedure to get the +/// CFAM Id from each configured Centaur. +/// +/// \note Normally we would implement test/bringup workarounds like the \a +/// i_setup parameter separately, however the setup of Centaur is at a level +/// of complexity where it makes sense to implement this override in a +/// mainline procedure. +int +_centaur_configuration_create(int i_bar, int i_slave, int i_setup); + + +/// Get a Centaur (MB) CFAM Chip Id +/// +/// \param[in] i_mb The index (0..PGP_NCENTAUR - 1) of the memory buffer being +/// queried. +/// +/// \returns A 32-bit value to be compared against the enumeration of known +/// CFAM ids. See \ref pgp_cfam_chip_ids. If the \a i_mb is invalid or the +/// Centaur is not configured or the G_centaurConfiguration is not valid then +/// (uint32_t)-1 is returned. +uint32_t mb_id(int i_mb); + + +/// Get a Centaur (MB) Chip Type +/// +/// \param[in] i_mb The index (0..PGP_NCENTAUR - 1) of the memory buffer being +/// queried. +/// +/// \returns An 8-bit value to be compared against the enumeration of known +/// CFAM chip types. See \ref pgp_cfam_chip_types. If the \a i_mb is invalid +/// or the Centaur is not configured or the G_centaurConfiguration is not +/// valid then (uint8_t)-1 is returned. +uint8_t mb_chip_type(int i_mb); + + +/// Get a Centaur (MB) CFAM Chip EC Level +/// +/// \param[in] i_mb The index (0..PGP_NCENTAUR - 1) of the memory buffer being +/// queried. +/// +/// \returns An 8-bit value; The high-order nibble is the major EC level and +/// the low-order nibble is the minor EC level. For example a value of 0x21 +/// indicates DD 2.1. If the \a i_mb is invalid or the Centaur is not +/// configured or the G_centaurConfiguration is not valid then (uint8_t)-1 is +/// returned. +uint8_t mb_ec_level(int i_mb); + +#endif // __ASSEMBLER + +#endif // __PGP_CENTAUR_H__ diff --git a/src/ssx/pgp/pgp_common.h b/src/ssx/pgp/pgp_common.h new file mode 100755 index 0000000..305f7c2 --- /dev/null +++ b/src/ssx/pgp/pgp_common.h @@ -0,0 +1,717 @@ +#ifndef __PGP_COMMON_H__ +#define __PGP_COMMON_H__ + +// $Id: pgp_common.h,v 1.4 2014/02/03 01:30:35 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_common.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_common.h +/// \brief Common header for SSX and PMX versions of PgP +/// +/// This header is maintained as part of the SSX port for PgP, but needs to be +/// physically present in the PMX area to allow dropping PMX code as a whole +/// to other teams. + +// -*- WARNING: This file is maintained as part of SSX. Do not edit in -*- +// -*- the PMX area as your edits will be lost. -*- + +#ifndef __ASSEMBLER__ +#include <stdint.h> +extern unsigned int g_ocb_timer_divider; //grm +#endif + +//////////////////////////////////////////////////////////////////////////// +// Configuration +//////////////////////////////////////////////////////////////////////////// + +#define PGP_NCORES 16 +#define PGP_NCORE_PARTITIONS 4 +#define PGP_NMCS 8 +#define PGP_NCENTAUR 8 +#define PGP_NTHREADS 8 +#define PGP_NDTSCPM 4 + +#ifndef PROCESSOR_EC_LEVEL +#define MURANO_DD10 1 +#else +#define MURANO_DD10 0 +#endif + + +//////////////////////////////////////////////////////////////////////////// +// Clocking +//////////////////////////////////////////////////////////////////////////// +// +// The SSX timebase is driven by the pervasive clock, which is nest / 4. This +// will typically be 600MHz, but may be 500MHz for power-constrained system +// designs. + +/// The pervasive hang timer divider used for the OCB timer +/// +/// This is supposed to yield an approximately 1us timer, however for MURANO +/// DD10 we need to use an approximate 64us timer + +#if MURANO_DD10 +#define OCB_TIMER_DIVIDER_DEFAULT (64 * 512) +#else +#define OCB_TIMER_DIVIDER_DEFAULT 512 +#endif + +/// This is set to the above default at compile time but may be updated +/// at run time. grm +#define OCB_TIMER_DIVIDER g_ocb_timer_divider + +/// The OCB timer frequency +#define OCB_TIMER_FREQUENCY_HZ (SSX_TIMEBASE_FREQUENCY_HZ / OCB_TIMER_DIVIDER) + +/// The pervasive hang timer divider used for the PMC (same as OCB timer) +#define PMC_TIMER_DIVIDER OCB_TIMER_DIVIDER + +/// The PMC hang pulse frequency +#define PMC_HANG_PULSE_FREQUENCY_HZ \ + (SSX_TIMEBASE_FREQUENCY_HZ / PMC_TIMER_DIVIDER) + +/// The pervasive hang timer divider for PCBS 'fast' timers +/// +/// This timer yeilds an approximate 100ns pulse with a 2.4 GHz pervasive clock +#define PCBS_FAST_TIMER_DIVIDER 64 + +/// The pervasive hang timer divider for PCBS 'slow' timers +/// +/// This timer yeilds an approximate 1us pulse with a 2.4 GHz pervasive clock +#define PCBS_SLOW_TIMER_DIVIDER 512 + +/// The PCBS slow divider frequency +#define PCBS_SLOW_HANG_PULSE_FREQUENCY_HZ \ + (SSX_TIMEBASE_FREQUENCY_HZ / PCBS_SLOW_TIMER_DIVIDER) + +/// The PCBS occ heartbeat pulse is predivided in hardware by 64 +#define PCBS_HEARTBEAT_DIVIDER \ + (PCBS_SLOW_TIMER_DIVIDER * 64) + +/// The PCBS heartbeat pulse frequency +#define PCBS_HEARTBEAT_PULSE_FREQUENCY_HZ \ + (SSX_TIMEBASE_FREQUENCY_HZ / PCBS_HEARTBEAT_DIVIDER) + + + +//////////////////////////////////////////////////////////////////////////// +// OCI +//////////////////////////////////////////////////////////////////////////// + +// OCI Master Id assigments - required for PBA slave programming. These Ids +// also appear as bits 12:15 of the OCI register space addresses of the OCI +// registers for each device that contains OCI-addressable registers (GPE, +// PMC, PBA, SLW and OCB). + +#define OCI_MASTER_ID_PORE_GPE 0 +#define OCI_MASTER_ID_PMC 1 +#define OCI_MASTER_ID_PBA 2 +#define OCI_MASTER_ID_UNUSED 3 +#define OCI_MASTER_ID_PORE_SLW 4 +#define OCI_MASTER_ID_OCB 5 +#define OCI_MASTER_ID_OCC_ICU 6 +#define OCI_MASTER_ID_OCC_DCU 7 + + +//////////////////////////////////////////////////////////////////////////// +// IRQ +//////////////////////////////////////////////////////////////////////////// + +// The OCB interrupt controller consists of 2 x 32-bit controllers. Unlike +// PPC ASICs, the OCB controllers are _not_ cascaded. The combined +// controllers are presented to the application as if there were a single +// 64-bit interrupt controller, while the code underlying the abstraction +// manipulates the 2 x 32-bit controllers independently. +// +// Note that the bits named *RESERVED* are actually implemented in the +// controller, but the interrupt input is tied low. That means they can also +// be used as IPI targets. Logical bits 32..63 are not implemented. + +#define PGP_IRQ_DEBUGGER 0 /* 0x00 */ +#define PGP_IRQ_TRACE_TRIGGER 1 /* 0x01 */ +#define PGP_IRQ_OCC_ERROR 2 /* 0x02 */ +#define PGP_IRQ_PBA_ERROR 3 /* 0x03 */ +#define PGP_IRQ_SRT_ERROR 4 /* 0x04 */ +#define PGP_IRQ_PORE_SW_ERROR 5 /* 0x05 */ +#define PGP_IRQ_PORE_GPE0_FATAL_ERROR 6 /* 0x06 */ +#define PGP_IRQ_PORE_GPE1_FATAL_ERROR 7 /* 0x07 */ +#define PGP_IRQ_PORE_SBE_FATAL_ERROR 8 /* 0x08 */ +#define PGP_IRQ_PMC_ERROR 9 /* 0x09 */ +#define PGP_IRQ_OCB_ERROR 10 /* 0x0a */ +#define PGP_IRQ_SPIPSS_ERROR 11 /* 0x0b */ +#define PGP_IRQ_CHECK_STOP 12 /* 0x0c */ +#define PGP_IRQ_PMC_MALF_ALERT 13 /* 0x0d */ +#define PGP_IRQ_ADU_MALF_ALERT 14 /* 0x0e */ +#define PGP_IRQ_EXTERNAL_TRAP 15 /* 0x0f */ +#define PGP_IRQ_OCC_TIMER0 16 /* 0x10 */ +#define PGP_IRQ_OCC_TIMER1 17 /* 0x11 */ +#define PGP_IRQ_PORE_GPE0_ERROR 18 /* 0x12 */ +#define PGP_IRQ_PORE_GPE1_ERROR 19 /* 0x13 */ +#define PGP_IRQ_PORE_SBE_ERROR 20 /* 0x14 */ +#define PGP_IRQ_PMC_INTERCHIP_MSG_RECV 21 /* 0x15 */ +#define PGP_IRQ_RESERVED_22 22 /* 0x16 */ +#define PGP_IRQ_PORE_GPE0_COMPLETE 23 /* 0x17 */ +#define PGP_IRQ_PORE_GPE1_COMPLETE 24 /* 0x18 */ +#define PGP_IRQ_ADCFSM_ONGOING 25 /* 0x19 */ +#define PGP_IRQ_RESERVED_26 26 /* 0x1a */ +#define PGP_IRQ_PBA_OCC_PUSH0 27 /* 0x1b */ +#define PGP_IRQ_PBA_OCC_PUSH1 28 /* 0x1c */ +#define PGP_IRQ_PBA_BCDE_ATTN 29 /* 0x1d */ +#define PGP_IRQ_PBA_BCUE_ATTN 30 /* 0x1e */ +#define PGP_IRQ_RESERVED_31 31 /* 0x1f */ + +#define PGP_IRQ_RESERVED_32 32 /* 0x20 */ +#define PGP_IRQ_RESERVED_33 33 /* 0x21 */ +#define PGP_IRQ_STRM0_PULL 34 /* 0x22 */ +#define PGP_IRQ_STRM0_PUSH 35 /* 0x23 */ +#define PGP_IRQ_STRM1_PULL 36 /* 0x24 */ +#define PGP_IRQ_STRM1_PUSH 37 /* 0x25 */ +#define PGP_IRQ_STRM2_PULL 38 /* 0x26 */ +#define PGP_IRQ_STRM2_PUSH 39 /* 0x27 */ +#define PGP_IRQ_STRM3_PULL 40 /* 0x28 */ +#define PGP_IRQ_STRM3_PUSH 41 /* 0x29 */ +#define PGP_IRQ_RESERVED_42 42 /* 0x2a */ +#define PGP_IRQ_RESERVED_43 43 /* 0x2b */ +#define PGP_IRQ_PMC_VOLTAGE_CHANGE_ONGOING 44 /* 0x2c */ +#define PGP_IRQ_PMC_PROTOCOL_ONGOING 45 /* 0x2d */ +#define PGP_IRQ_PMC_SYNC 46 /* 0x2e */ +#define PGP_IRQ_PMC_PSTATE_REQUEST 47 /* 0x2f */ +#define PGP_IRQ_RESERVED_48 48 /* 0x30 */ +#define PGP_IRQ_RESERVED_49 49 /* 0x31 */ +#define PGP_IRQ_PMC_IDLE_EXIT 50 /* 0x32 */ +#define PGP_IRQ_PORE_SW_COMPLETE 51 /* 0x33 */ +#define PGP_IRQ_PMC_IDLE_ENTER 52 /* 0x34 */ +#define PGP_IRQ_RESERVED_53 53 /* 0x35 */ +#define PGP_IRQ_PMC_INTERCHIP_MSG_SEND_ONGOING 54 /* 0x36 */ +#define PGP_IRQ_OCI2SPIVID_ONGOING 55 /* 0x37 */ +#define PGP_IRQ_PMC_OCB_O2P_ONGOING 56 /* 0x38 */ +#define PGP_IRQ_PSSBRIDGE_ONGOING 57 /* 0x39 */ +#define PGP_IRQ_PORE_SBE_COMPLETE 58 /* 0x3a */ +#define PGP_IRQ_IPI0 59 /* 0x3b */ +#define PGP_IRQ_IPI1 60 /* 0x3c */ +#define PGP_IRQ_IPI2 61 /* 0x3d */ +#define PGP_IRQ_IPI3 62 /* 0x3e */ +#define PGP_IRQ_RESERVED_63 63 /* 0x3f */ + + +// Please keep the string definitions up-to-date as they are used for +// reporting in the Simics simulation. + +#define PGP_IRQ_STRINGS(var) \ + const char* var[64] = { \ + "PGP_IRQ_DEBUGGER", \ + "PGP_IRQ_TRACE_TRIGGER", \ + "PGP_IRQ_OCC_ERROR", \ + "PGP_IRQ_PBA_ERROR", \ + "PGP_IRQ_SRT_ERROR", \ + "PGP_IRQ_PORE_SW_ERROR", \ + "PGP_IRQ_PORE_GPE0_FATAL_ERROR", \ + "PGP_IRQ_PORE_GPE1_FATAL_ERROR", \ + "PGP_IRQ_PORE_SBE_FATAL_ERROR", \ + "PGP_IRQ_PMC_ERROR", \ + "PGP_IRQ_OCB_ERROR", \ + "PGP_IRQ_SPIPSS_ERROR", \ + "PGP_IRQ_CHECK_STOP", \ + "PGP_IRQ_PMC_MALF_ALERT", \ + "PGP_IRQ_ADU_MALF_ALERT", \ + "PGP_IRQ_EXTERNAL_TRAP", \ + "PGP_IRQ_OCC_TIMER0", \ + "PGP_IRQ_OCC_TIMER1", \ + "PGP_IRQ_PORE_GPE0_ERROR", \ + "PGP_IRQ_PORE_GPE1_ERROR", \ + "PGP_IRQ_PORE_SBE_ERROR", \ + "PGP_IRQ_PMC_INTERCHIP_MSG_RECV", \ + "PGP_IRQ_RESERVED_22", \ + "PGP_IRQ_PORE_GPE0_COMPLETE", \ + "PGP_IRQ_PORE_GPE1_COMPLETE", \ + "PGP_IRQ_ADCFSM_ONGOING", \ + "PGP_IRQ_RESERVED_26", \ + "PGP_IRQ_PBA_OCC_PUSH0", \ + "PGP_IRQ_PBA_OCC_PUSH1", \ + "PGP_IRQ_PBA_BCDE_ATTN", \ + "PGP_IRQ_PBA_BCUE_ATTN", \ + "PGP_IRQ_RESERVED_31", \ + "PGP_IRQ_RESERVED_32", \ + "PGP_IRQ_RESERVED_33", \ + "PGP_IRQ_STRM0_PULL", \ + "PGP_IRQ_STRM0_PUSH", \ + "PGP_IRQ_STRM1_PULL", \ + "PGP_IRQ_STRM1_PUSH", \ + "PGP_IRQ_STRM2_PULL", \ + "PGP_IRQ_STRM2_PUSH", \ + "PGP_IRQ_STRM3_PULL", \ + "PGP_IRQ_STRM3_PUSH", \ + "PGP_IRQ_RESERVED_42", \ + "PGP_IRQ_RESERVED_43", \ + "PGP_IRQ_PMC_VOLTAGE_CHANGE_ONGOING", \ + "PGP_IRQ_PMC_PROTOCOL_ONGOING", \ + "PGP_IRQ_PMC_SYNC", \ + "PGP_IRQ_PMC_PSTATE_REQUEST", \ + "PGP_IRQ_RESERVED_48", \ + "PGP_IRQ_RESERVED_49", \ + "PGP_IRQ_PMC_IDLE_EXIT", \ + "PGP_IRQ_PORE_SW_COMPLETE", \ + "PGP_IRQ_PMC_IDLE_ENTER", \ + "PGP_IRQ_RESERVED_53", \ + "PGP_IRQ_PMC_INTERCHIP_MSG_SEND_ONGOING", \ + "PGP_IRQ_OCI2SPIVID_ONGOING", \ + "PGP_IRQ_PMC_OCB_O2P_ONGOING", \ + "PGP_IRQ_PSSBRIDGE_ONGOING", \ + "PGP_IRQ_PORE_SBE_COMPLETE", \ + "PGP_IRQ_IPI0", \ + "PGP_IRQ_IPI1", \ + "PGP_IRQ_IPI2", \ + "PGP_IRQ_IPI3 (ASYNC-IPI)", \ + "PGP_IRQ_RESERVED_63" \ + }; + + +/// This constant is used to define the size of the table of interrupt handler +/// structures as well as a limit for error checking. The entire 64-bit +/// vector is now in use. + +#define PPC405_IRQS 64 + + +// Note: All standard-product IPI uses are declared here to avoid conflicts +// Validation- and lab-only IPI uses are documented in validation.h + +/// The deferred callback queue interrupt +/// +/// This IPI is reserved for use of the async deferred callback mechanism. +/// This IPI is used by both critical and noncritical async handlers to +/// activate the deferred callback mechanism. +#define PGP_IRQ_ASYNC_IPI PGP_IRQ_IPI3 + + +/// The PTS completion queue intererupt +/// +/// This IPI is reserved for use of the PTS completion queues. A single +/// interrupt serves PTS for both GPE0 and GPE1. Note that as defined here, +/// PTS completion takes precedence over other ASYNC processing, however in +/// reality they both run callbacks preemptible so they will tend to be more +/// or less at the same priority. If this is a problem then they could be +/// combined onto a single interrupt and handled with the appropriate priority +/// in the async_callback_handler_full(). + +#define PGP_IRQ_PTS_IPI PGP_IRQ_IPI2 + + +#ifndef __ASSEMBLER__ + +/// This expression recognizes only those IRQ numbers that have named +/// (non-reserved) interrupts in the OCB interrupt controller. + +// There are so many invalid interrupts now that it's a slight improvement in +// code size to let the compiler optimize the invalid IRQs to a bit mask for +// the comparison. + +#define PGP_IRQ_VALID(irq) \ + ({unsigned __irq = (unsigned)(irq); \ + ((__irq < PPC405_IRQS) && \ + ((PGP_IRQ_MASK64(__irq) & \ + (PGP_IRQ_MASK64(PGP_IRQ_RESERVED_22) | \ + PGP_IRQ_MASK64(PGP_IRQ_RESERVED_26) | \ + PGP_IRQ_MASK64(PGP_IRQ_RESERVED_31) | \ + PGP_IRQ_MASK64(PGP_IRQ_RESERVED_32) | \ + PGP_IRQ_MASK64(PGP_IRQ_RESERVED_33) | \ + PGP_IRQ_MASK64(PGP_IRQ_RESERVED_42) | \ + PGP_IRQ_MASK64(PGP_IRQ_RESERVED_43) | \ + PGP_IRQ_MASK64(PGP_IRQ_RESERVED_48) | \ + PGP_IRQ_MASK64(PGP_IRQ_RESERVED_49) | \ + PGP_IRQ_MASK64(PGP_IRQ_RESERVED_53) | \ + PGP_IRQ_MASK64(PGP_IRQ_RESERVED_63))) == 0));}) + +/// This is a 32-bit mask, with big-endian bit (irq % 32) set. +#define PGP_IRQ_MASK32(irq) (((uint32_t)0x80000000) >> ((irq) % 32)) + +/// This is a 64-bit mask, with big-endian bit 'irq' set. +#define PGP_IRQ_MASK64(irq) (0x8000000000000000ull >> (irq)) + +#endif /* __ASSEMBLER__ */ + + +//////////////////////////////////////////////////////////////////////////// +// OCB +//////////////////////////////////////////////////////////////////////////// + +/// The base address of the OCI control register space +#define OCI_REGISTER_SPACE_BASE 0x40000000 + +/// The base address of the entire PIB port mapped by the OCB. The +/// OCB-contained PIB registers are based at OCB_PIB_BASE. +#define OCB_PIB_SLAVE_BASE 0x00060000 + +/// The size of the OCI control register address space +/// +/// There are at most 8 slaves, each of which maps 2**16 bytes of register +/// address space. +#define OCI_REGISTER_SPACE_SIZE POW2_32(19) + +/// This macro converts an OCI register space address into a PIB address as +/// seen through the OCB direct bridge. +#define OCI2PIB(addr) ((((addr) & 0x0007ffff) >> 3) + OCB_PIB_SLAVE_BASE) + + +// OCB communication channel constants + +#define OCB_INDIRECT_CHANNELS 4 + +#define OCB_RW_READ 0 +#define OCB_RW_WRITE 1 + +#define OCB_STREAM_MODE_DISABLED 0 +#define OCB_STREAM_MODE_ENABLED 1 + +#define OCB_STREAM_TYPE_LINEAR 0 +#define OCB_STREAM_TYPE_CIRCULAR 1 + +#define OCB_INTR_ACTION_FULL 0 +#define OCB_INTR_ACTION_NOT_FULL 1 +#define OCB_INTR_ACTION_EMPTY 2 +#define OCB_INTR_ACTION_NOT_EMPTY 3 + +#ifndef __ASSEMBLER__ + +// These macros select OCB interrupt controller registers based on the IRQ +// number. + +#define OCB_OIMR_AND(irq) (((irq) & 0x20) ? OCB_OIMR1_AND : OCB_OIMR0_AND) +#define OCB_OIMR_OR(irq) (((irq) & 0x20) ? OCB_OIMR1_OR : OCB_OIMR0_OR) + +#define OCB_OISR(irq) (((irq) & 0x20) ? OCB_OISR1 : OCB_OISR0) +#define OCB_OISR_AND(irq) (((irq) & 0x20) ? OCB_OISR1_AND : OCB_OISR0_AND) +#define OCB_OISR_OR(irq) (((irq) & 0x20) ? OCB_OISR1_OR : OCB_OISR0_OR) + +#define OCB_OIEPR(irq) (((irq) & 0x20) ? OCB_OIEPR1 : OCB_OIEPR0) +#define OCB_OITR(irq) (((irq) & 0x20) ? OCB_OITR1 : OCB_OITR0) +#define OCB_OCIR(irq) (((irq) & 0x20) ? OCB_OCIR1 : OCB_OCIR0) +#define OCB_OUDER(irq) (((irq) & 0x20) ? OCB_OUDER1 : OCB_OUDER0) + +#endif /* __ASSEMBLER__ */ + + +//////////////////////////////////////////////////////////////////////////// +// PMC +//////////////////////////////////////////////////////////////////////////// + +#ifndef __ASSEMBLER__ + +/// A Pstate type +/// +/// Pstates are signed, but our register access macros operate on unsigned +/// values. To avoid bugs, Pstate register fields should always be extracted +/// to a variable of type Pstate. If the size of Pstate variables ever +/// changes we will have to revisit this convention. +typedef int8_t Pstate; + +/// A DPLL frequency code +/// +/// DPLL frequency codes moved from 8 to 9 bits going from P7 to P8 +typedef uint16_t DpllCode; + +/// A VRM11 VID code +typedef uint8_t Vid11; + +#endif /* __ASSEMBLER__ */ + +/// The minimum Pstate +#define PSTATE_MIN -128 + +/// The maximum Pstate +#define PSTATE_MAX 127 + +/// The minimum \e legal DPLL frequency code +/// +/// This is ~1GHz with a 33.3MHz tick frequency. +#define DPLL_MIN 0x01e + +/// The maximum DPLL frequency code +#define DPLL_MAX 0x1ff + +/// The minimum \a legal (non-power-off) VRM11 VID code +#define VID11_MIN 0x02 + +/// The maximum \a legal (non-power-off) VRM11 VID code +#define VID11_MAX 0xfd + + +//////////////////////////////////////////////////////////////////////////// +// PCB +//////////////////////////////////////////////////////////////////////////// + +/// Convert a core chiplet 0 SCOM address to the equivalent address for any +/// other core chiplet. +/// +/// Note that it is unusual to address core chiplet SCOMs directly. Normally +/// this is done as part of a GPE program where the program iterates over core +/// chiplets, using the chiplet-0 address + a programmable offset held in a +/// chiplet address register. Therefore the only address macro defined is the +/// chiplet-0 address. This macro is used for the rare cases of explicit +/// getscom()/ putscom() to a particular chiplet. + +#define CORE_CHIPLET_ADDRESS(addr, core) ((addr) + ((core) << 24)) + + +// PCB Error codes + +#define PCB_ERROR_NONE 0 +#define PCB_ERROR_RESOURCE_OCCUPIED 1 +#define PCB_ERROR_CHIPLET_OFFLINE 2 +#define PCB_ERROR_PARTIAL_GOOD 3 +#define PCB_ERROR_ADDRESS_ERROR 4 +#define PCB_ERROR_CLOCK_ERROR 5 +#define PCB_ERROR_PACKET_ERROR 6 +#define PCB_ERROR_TIMEOUT 7 + +// PCB Multicast modes + +#define PCB_MULTICAST_OR 0 +#define PCB_MULTICAST_AND 1 +#define PCB_MULTICAST_SELECT 2 +#define PCB_MULTICAST_COMPARE 4 +#define PCB_MULTICAST_WRITE 5 + +/// \defgroup pcb_multicast_groups PCB Multicast Groups +/// +/// Technically the multicast groups are programmable; This is the multicast +/// grouping established by proc_sbe_chiplet_init(). +/// +/// - Group 0 : All functional chiplets (PRV PB XBUS ABUS PCIE TPCEX) +/// - Group 1 : All functional EX chiplets (no cores) +/// - Group 2 : All functional EX chiplets (core only) +/// - Group 3 : All functional chiplets except pervasive (PRV) +/// +/// @{ + +#define MC_GROUP_ALL 0 +#define MC_GROUP_EX 1 +#define MC_GROUP_EX_CORE 2 +#define MC_GROUP_ALL_BUT_PRV 3 + +/// @} + + +/// Convert any SCOM address to a multicast address +#define MC_ADDRESS(address, group, mode) \ + (((address) & 0x00ffffff) | ((0x40 | ((mode) << 3) | (group)) << 24)) + + + +//////////////////////////////////////////////////////////////////////////// +// PBA +//////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////// +// Macros for fields of PBA_MODECTL +//////////////////////////////////// + +/// The 64KB OCI HTM marker space is enabled by default at 0x40070000 +/// +/// See the comments for pgp_trace.h + +#define PBA_OCI_MARKER_BASE 0x40070000 + + +// SSX Kernel reserved trace addresses, see pgp_trace.h. + +#define SSX_TRACE_CRITICAL_IRQ_ENTRY_BASE 0xf000 +#define SSX_TRACE_CRITICAL_IRQ_EXIT_BASE 0xf100 +#define SSX_TRACE_NONCRITICAL_IRQ_ENTRY_BASE 0xf200 +#define SSX_TRACE_NONCRITICAL_IRQ_EXIT_BASE 0xf300 +#define SSX_TRACE_THREAD_SWITCH_BASE 0xf400 +#define SSX_TRACE_THREAD_SLEEP_BASE 0xf500 +#define SSX_TRACE_THREAD_WAKEUP_BASE 0xf600 +#define SSX_TRACE_THREAD_SEMAPHORE_PEND_BASE 0xf700 +#define SSX_TRACE_THREAD_SEMAPHORE_POST_BASE 0xf800 +#define SSX_TRACE_THREAD_SEMAPHORE_TIMEOUT_BASE 0xf900 +#define SSX_TRACE_THREAD_SUSPENDED_BASE 0xfa00 +#define SSX_TRACE_THREAD_DELETED_BASE 0xfb00 +#define SSX_TRACE_THREAD_COMPLETED_BASE 0xfc00 +#define SSX_TRACE_THREAD_MAPPED_RUNNABLE_BASE 0xfd00 +#define SSX_TRACE_THREAD_MAPPED_SEMAPHORE_PEND_BASE 0xfe00 +#define SSX_TRACE_THREAD_MAPPED_SLEEPING_BASE 0xff00 + + +// Please keep the string definitions up to date as they are used for +// reporting in the Simics simulation. + +#define SSX_TRACE_STRINGS(var) \ + const char* var[16] = { \ + "Critical IRQ Entry ", \ + "Critical IRQ Exit ", \ + "Noncritical IRQ Entry ", \ + "Noncritical IRQ Exit ", \ + "Thread Switch ", \ + "Thread Blocked : Sleep ", \ + "Thread Unblocked : Wakeup ", \ + "Thread Blocked : Semaphore ", \ + "Thread Unblocked : Semaphore ", \ + "Thread Unblocked : Sem. Timeout", \ + "Thread Suspended ", \ + "Thread Deleted ", \ + "Thread Completed ", \ + "Thread Mapped Runnable ", \ + "Thread Mapped Semaphore Pend. ", \ + "Thread Mapped Sleeping ", \ + }; + + +// PBA transaction sizes for the block copy engines + +#define PBA_BCE_OCI_TRANSACTION_32_BYTES 0 +#define PBA_BCE_OCI_TRANSACTION_64_BYTES 1 +#define PBA_BCE_OCI_TRANSACTION_8_BYTES 2 + + +// PBAX communication channel constants + +#define PBAX_CHANNELS 2 + +#define PBAX_INTR_ACTION_FULL 0 +#define PBAX_INTR_ACTION_NOT_FULL 1 +#define PBAX_INTR_ACTION_EMPTY 2 +#define PBAX_INTR_ACTION_NOT_EMPTY 3 + + +// PBA Write Buffer fields + +#define PBA_WBUFVALN_STATUS_EMPTY 0x01 +#define PBA_WBUFVALN_STATUS_GATHERING 0x02 +#define PBA_WBUFVALN_STATUS_WAIT 0x04 +#define PBA_WBUFVALN_STATUS_WRITING 0x08 +#define PBA_WBUFVALN_STATUS_CRESPERR 0x10 + + +//////////////////////////////////////////////////////////////////////////// +// VRM +//////////////////////////////////////////////////////////////////////////// + +// These are the command types recognized by the VRMs + +#define VRM_WRITE_VOLTAGE 0x0 +#define VRM_READ_STATE 0xc +#define VRM_READ_VOLTAGE 0x3 + +// Voltage rail designations for the read voltage command +#define VRM_RD_VDD_RAIL 0x0 +#define VRM_RD_VCS_RAIL 0x1 + + +//////////////////////////////////////////////////////////////////////////// +// OHA +//////////////////////////////////////////////////////////////////////////// + +// Power proxy trace record idle state encodings. These encodings are unique +// to the Power proxy trace record. + +#define PPT_IDLE_NON_IDLE 0x0 +#define PPT_IDLE_NAP 0x1 +#define PPT_IDLE_LIGHT_SLEEP 0x2 +#define PPT_IDLE_FAST_SLEEP 0x3 +#define PPT_IDLE_DEEP_SLEEP 0x4 +#define PPT_IDLE_LIGHT_WINKLE 0x5 +#define PPT_IDLE_FAST_WINKLE 0x6 +#define PPT_IDLE_DEEP_WINKLE 0x7 + + +//////////////////////////////////////////////////////////////////////////// +// PC +//////////////////////////////////////////////////////////////////////////// + +// SPRC numbers for PC counters. The low-order 3 bits are always defined as +// 0. The address can also be modified by OR-ing in 0x400 to indicate +// auto-increment addressing. Note that the frequency-sensitivity counters +// are called "workrate" counters in the hardware documentation. +// +// Notes on the throttle counters: +// +// SPRN_IFU_THROTTLE_COUNTER +// Cycles the IFU throttle was actually blocking fetch +// +// <= if_pc_didt_throttle_blocked +// +// SPRN_ISU_THROTTLE_COUNTER +// Cycles that ISU throttle was active and modeably IFU throttle request +// was not +// +// <= sd_pc_uthrottle_active AND +// (NOT scom_isuonly_count_mode OR NOT trigger_didt_throttle) +// +// SPRN_IFU_ACTIVE_COUNTER +// Cycles that IFU throttle active input is asserted +// +// <= if_pc_didt_throttle_active + + +/// \note The OCC SPRC/SPRD hardware has a bug that makes it such that the OCC +/// SPRC increments whenever the OCC SPRD is accessed, regardless of the +/// setting of the SPRN_PC_AUTOINCREMENT bit. This bug won't be fixed. + +#define SPRN_CORE_INSTRUCTION_DISPATCH 0x200 +#define SPRN_CORE_INSTRUCTION_COMPLETE 0x208 +#define SPRN_CORE_FREQUENCY_SENSITIVITY_BUSY 0x210 +#define SPRN_CORE_FREQUENCY_SENSITIVITY_FINISH 0x218 +#define SPRN_CORE_RUN_CYCLE 0x220 +#define SPRN_CORE_RAW_CYCLE 0x228 +#define SPRN_CORE_MEM_HIER_A 0x230 +#define SPRN_CORE_MEM_HIER_B 0x238 +#define SPRN_CORE_MEM_C_LPAR(p) (0x240 + (8 * (p))) +#define SPRN_WEIGHTED_INSTRUCTION_PROCESSING 0x260 +#define SPRN_WEIGHTED_GPR_REGFILE_ACCESS 0x268 +#define SPRN_WEIGHTED_VRF_REGFILE_ACCESS 0x270 +#define SPRN_WEIGHTED_FLOATING_POINT_ISSUE 0x278 +#define SPRN_WEIGHTED_CACHE_READ 0x280 +#define SPRN_WEIGHTED_CACHE_WRITE 0x288 +#define SPRN_WEIGHTED_ISSUE 0x290 +#define SPRN_WEIGHTED_CACHE_ACCESS 0x298 +#define SPRN_WEIGHTED_VSU_ISSUE 0x2a0 +#define SPRN_WEIGHTED_FXU_ISSUE 0x2a8 + +#define SPRN_THREAD_RUN_CYCLES(t) (0x2b0 + (0x20 * (t))) +#define SPRN_THREAD_INSTRUCTION_COMPLETE(t) (0x2b8 + (0x20 * (t))) +#define SPRN_THREAD_MEM_HIER_A(t) (0x2c0 + (0x20 * (t))) +#define SPRN_THREAD_MEM_HIER_B(t) (0x2c8 + (0x20 * (t))) + +#define SPRN_IFU_THROTTLE_COUNTER 0x3b0 +#define SPRN_ISU_THROTTLE_COUNTER 0x3b8 +#define SPRN_IFU_ACTIVE_COUNTER 0x3c0 + +#define SPRN_PC_AUTOINCREMENT 0x400 + + +//////////////////////////////////////////////////////////////////////////// +// Centaur +//////////////////////////////////////////////////////////////////////////// + +// DIMM sensor status codes + +/// The next sampling period began before this sensor was read or the master +/// enable is off, or the individual sensor is disabled. If the subsequent +/// read completes on time, this will return to valid reading. Sensor data may +/// be accurate, but stale. If due to a stall, the StallError FIR will be +/// set. +#define DIMM_SENSOR_STATUS_STALLED 0 + +/// The sensor data was not returned correctly either due to parity +/// error or PIB bus error code. Will return to valid if the next PIB +/// access to this sensor is valid, but a FIR will be set; Refer to FIR +/// for exact error. Sensor data should not be considered valid while +/// this code is present. +#define DIMM_SENSOR_STATUS_ERROR 1 + +/// Sensor data is valid, and has been valid since the last time this +/// register was read. +#define DIMM_SENSOR_STATUS_VALID_OLD 2 + +/// Sensor data is valid and has not yet been read by a SCOM. The status code +/// return to DIMM_SENSOR_STATUS_VALID_OLD after this register is read. +#define DIMM_SENSOR_STATUS_VALID_NEW 3 + + +#endif /* __PGP_COMMON_H__ */ diff --git a/src/ssx/pgp/pgp_core.h b/src/ssx/pgp/pgp_core.h new file mode 100755 index 0000000..59edb26 --- /dev/null +++ b/src/ssx/pgp/pgp_core.h @@ -0,0 +1,20 @@ +#ifndef __PGP_CORE_H__ +#define __PGP_CORE_H__ + +// $Id: pgp_core.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_core.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_core.h +/// \brief PgP core units header. Local and mechanically generated macros. + +#include "pc_register_addresses.h" +#include "pc_firmware_registers.h" +#include "sensors_register_addresses.h" +#include "sensors_firmware_registers.h" + +#endif /* __PGP_CORE_H__ */ diff --git a/src/ssx/pgp/pgp_id.c b/src/ssx/pgp/pgp_id.c new file mode 100644 index 0000000..0b4d4d7 --- /dev/null +++ b/src/ssx/pgp/pgp_id.c @@ -0,0 +1,135 @@ +// $Id: pgp_id.c,v 1.2 2014/02/03 01:30:35 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_id.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_id.h +/// \brief PgP chip and EC-level identification + chip configuration + +#include "ssx.h" +#include "pgp_config.h" + + +// Note: These cached variables are all declared as 64 bits, noncacheable so +// that that they are also available as-is to PORE programs. + +uint64_t G_node_id SECTION_ATTRIBUTE(".noncacheable") = 0; +uint64_t G_chip_id SECTION_ATTRIBUTE(".noncacheable") = 0; +uint64_t G_cfam_id SECTION_ATTRIBUTE(".noncacheable") = 0; +uint64_t G_cfam_chip_type SECTION_ATTRIBUTE(".noncacheable") = 0; +uint64_t G_cfam_ec_level SECTION_ATTRIBUTE(".noncacheable") = 0; + +void +_pgp_get_ids(void) +{ + tpc_gp0_t gp0; + tpc_device_id_t deviceId; + cfam_id_t cfamId; + + getscom(TPC_GP0, &(gp0.value)); + G_node_id = gp0.fields.tc_node_id_dc; + G_chip_id = gp0.fields.tc_chip_id_dc; + + getscom(TPC_DEVICE_ID, &(deviceId.value)); + G_cfam_id = cfamId.value = deviceId.fields.cfam_id; + G_cfam_chip_type = cfamId.chipType; + G_cfam_ec_level = (cfamId.majorEc << 4) | cfamId.minorEc; +} + + +uint8_t +node_id(void) +{ + return G_node_id; +} + +uint8_t +chip_id(void) +{ + return G_chip_id; +} + +uint32_t +cfam_id(void) +{ + return G_cfam_id; +} + +uint8_t +cfam_chip_type(void) +{ + return G_cfam_chip_type; +} + +uint8_t +cfam_ec_level(void) +{ + return G_cfam_ec_level; +} + + +// The chiplet configuration is computed by doing a "select-mode" multicast to +// the all-functional-chiplets-core group. Correctness here depends on the +// convention that the "select" bit number will always be 0. We check just to +// be sure. Since this is called from initialization code there is no recourse +// here except to panic in the event of error. + +// Note: Ex-chiplets start at chiplet 16 and are left-justified in the +// ChipConfig. + + +ChipConfig G_chip_configuration SECTION_ATTRIBUTE(".noncacheable") = 0; +uint64_t G_core_configuration SECTION_ATTRIBUTE(".noncacheable") = 0; + +/// \bug This API currently only computes the core configuration. It needs to +/// be extended to also compute the MC and Centaur configuration. +/// +/// \bug in Simics we're doing this based on the PMC_CORE_DECONFIGURATION_REG +/// pending Simics support for the base pervasive functionality + +void +_pgp_get_chip_configuration(void) +{ + if (SIMICS_ENVIRONMENT) { + + pmc_core_deconfiguration_reg_t pcdr; + + pcdr.value = in32(PMC_CORE_DECONFIGURATION_REG); + G_chip_configuration = + ~((uint64_t)(pcdr.fields.core_chiplet_deconf_vector) << 48); + + } else { + + uint64_t select, configuration; + int rc; + + rc = getscom(0x000f0008, &select); /* TP CHIPLET SELECT */ + if (rc) SSX_PANIC(PGP_ID_SCOM_ERROR_SELECT); + if (select != 0) SSX_PANIC(PGP_ID_SELECT_ERROR); + + rc = getscom(MC_ADDRESS(0x000f0012, + MC_GROUP_EX_CORE, + PCB_MULTICAST_SELECT), + &configuration); + if (rc) SSX_PANIC(PGP_ID_SCOM_ERROR_CONFIG); + + G_chip_configuration = (configuration << 16) & 0xffff000000000000ull; + } + + G_core_configuration = G_chip_configuration & 0xffff000000000000ull; +} + + +uint32_t core_configuration(void) +{ + return G_core_configuration >> 32; +} + + + + + + diff --git a/src/ssx/pgp/pgp_id.h b/src/ssx/pgp/pgp_id.h new file mode 100644 index 0000000..2b0ecab --- /dev/null +++ b/src/ssx/pgp/pgp_id.h @@ -0,0 +1,183 @@ +#ifndef __PGP_ID_H__ +#define __PGP_ID_H__ + +// $Id: pgp_id.h,v 1.2 2014/02/03 01:30:35 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_id.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_id.h +/// \brief PgP chip and EC-level identification + chip configuration +/// +/// During initialization the device identification SCOM registers are read +/// and cached. +/// +/// The node and chip ids are read from TPC_GP0 and stored as global +/// variables, accessible through the node_id() and chip_id() APIs. The +/// global variables are available to PORE programs. +/// +/// The TPC_DEVICE_ID register is also read, deconstructed and stored in +/// global variables. APIs defined here provide access to the fields of the +/// device identification to support run-time behavior based on the chip type +/// and EC level of the POWER8 chip containing the OCC. The global variables +/// are available to PORE programs. +/// +/// - cfam_id() : Obtain the full chip identification as a 32-bit CFAM id +/// - cfam_chip_type() : Obtain the 8-bit CFAM chip type +/// - cfam_ec_level() : Obtain an 8-bit CFAM EC level +/// +/// For example, to identify a chip as Murano DD1.0, one could use either +/// method shown below: +/// +/// \code +/// +/// if (cfam_id() == CFAM_CHIP_ID_MURANO_10) { ... } +/// +/// if ((cfam_chip_type() == CFAM_CHIP_TYPE_MURANO) && +/// (cfam_ec_level() == 0x10)) { ... } +/// +/// \encode + +// Error/Panic Codes + +#define PGP_ID_SCOM_ERROR_SELECT 0x00747401 +#define PGP_ID_SCOM_ERROR_CONFIG 0x00747402 +#define PGP_ID_SELECT_ERROR 0x00747403 + + +#ifndef __ASSEMBLER__ + +#include <stdint.h> +#include "tpc_firmware_registers.h" +#include "pgp_config.h" + + +/// Get TPC device identification (internal API, called once from __pgp_setup(). +void +_pgp_get_ids(void); + +/// Get the TPC Node Id +uint8_t node_id(void); + +/// Get the TPC Chip Id +uint8_t chip_id(void); + +/// Get the CFAM Chip Id +/// +/// \returns A 32-bit value to be compared against the enumeration of known +/// CFAM ids. See \ref pgp_cfam_chip_ids. +uint32_t cfam_id(void); + +/// Get the CFAM Chip Type +/// +/// \returns An 8-bit value to be compared against the enumeration of known +/// CFAM chip types. See \ref pgp_cfam_chip_types. +uint8_t cfam_chip_type(void); + +/// Get the CFAM Chip EC Level +/// +/// \returns An 8-bit value; The high-order nibble is the major EC level and +/// the low-order nibble is the minor EC level. Fore example a value of 0x21 +/// indicates DD 2.1. +uint8_t cfam_ec_level(void); + + +/// Compute the chip configuration (internal API, called once from __pgp_setup(). +void +_pgp_get_chip_configuration(void); + +/// Get the core configuration +/// +/// The return value is a 32 bit integer with big-endian bits set to indicate +/// valid cores. +uint32_t +core_configuration(void); + + +#endif // __ASSEMBLER__ + + +/// \defgroup pgp_cfam_chip_types PGP CFAM Chip Types (Including Centaur) +/// +/// The CFAM Chip Type is an 8-bit value that uniquely identfies a chip +/// architecture. +/// +/// @{ + +#define CFAM_CHIP_TYPE_CENTAUR 0xe9 +#define CFAM_CHIP_TYPE_VENICE 0xea +#define CFAM_CHIP_TYPE_MURANO 0xef + +/// @} + + +/// \defgroup pgp_cfam_chip_ids PGP CFAM Chip Ids (Including Centaur) +/// +/// The CFAM Chip ID is a 32-bit value that uniquely identfies a chip and its +/// EC level. +/// +/// The reference: +/// +/// - https://eclipz.pok.ibm.com/sys/ras/docs/cfam_ids.txt +/// +/// The interpretation: +/// +/// MlmCC049 +/// +/// M - Major EC (RIT-A) level +/// l - 2:Austin, 6:Poughkeepsie +/// m - Minor EC (RIT-B) level +/// CC - 0xE9:Centaur, 0xEA:Venice, 0xEF:Murano +/// 049 - IBM (Except for buggy 0x001 in Murano DD1.X) +/// +/// @{ + +#define CFAM_CHIP_ID_VENICE_10 0x120ea049 +#define CFAM_CHIP_ID_VENICE_20 0x220ea049 +#define CFAM_CHIP_ID_VENICE_21 0x221ea049 + +#define CFAM_CHIP_ID_MURANO_10 0x120ef001 +#define CFAM_CHIP_ID_MURANO_11 0x121ef001 +#define CFAM_CHIP_ID_MURANO_12 0x122ef001 +#define CFAM_CHIP_ID_MURANO_13 0x123ef001 +#define CFAM_CHIP_ID_MURANO_20 0x220ef049 +#define CFAM_CHIP_ID_MURANO_21 0x221ef049 + +#define CFAM_CHIP_ID_CENTAUR_10 0x160e9049 +#define CFAM_CHIP_ID_CENTAUR_20 0x260e9049 + + +#ifndef __ASSEMBLER__ + +/// The CFAM ID as a set of fields + +typedef union { +#ifdef _BIG_ENDIAN + struct { + uint32_t majorEc : 4; + uint32_t location : 4; + uint32_t minorEc : 4; + uint32_t chipType : 8; + uint32_t vendor : 12; + }; +#else + struct { + uint32_t vendor : 12; + uint32_t chipType : 8; + uint32_t minorEc : 4; + uint32_t location : 4; + uint32_t majorEc : 4; + }; +#endif // _BIG_ENDIAN + uint32_t value; + +} cfam_id_t; + +#endif // __ASSEMBLER__ + +/// @} + +#endif // __PGP_ID_H__ diff --git a/src/ssx/pgp/pgp_init.c b/src/ssx/pgp/pgp_init.c new file mode 100755 index 0000000..4e28014 --- /dev/null +++ b/src/ssx/pgp/pgp_init.c @@ -0,0 +1,340 @@ +// $Id: pgp_init.c,v 1.2 2014/03/14 16:34:34 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_init.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_init.c +/// \brief SSX initialization for PgP +/// +/// The entry points in this routine are used during initialization. This +/// code space can be deallocated and reassigned after application +/// initialization if required. + +#include "ssx.h" +#include "pgp_vrm.h" +#include "simics_stdio.h" +#include "string_stream.h" + +#if USE_RTX_IO +// This file is not avilable to OCC FW builds +#include "rtx_stdio.h" +#endif + +// We need to make sure that the PLB arbiter is set up correctly to obtain +// highest performance in the PgP environment, and that PLB error reporting is +// appropriate. + +// The PLB arbiter is configured to support fair arbitration of equal-priority +// requests, however we don't set priorities here. The default settings have +// been found to be acceptible so far. We do enable arbiter pipelining however. + +// We do set the "plbarb_lockerr" bit so that the PLB arbiter will trap and +// hold the first PLB timeout address. + +static void +plb_arbiter_setup() +{ + plb_pacr_t pacr; + ocb_ocichsw_t oo; + + pacr.value = 0; + pacr.fields.ppm = 1; /* Fair arbitration */ + pacr.fields.hbu = 1; /* High bus utilization */ + pacr.fields.rdp = 1; /* 2-deep read pipelining */ + pacr.fields.wrp = 1; /* 2-deep write pipelining */ + mtdcr(PLB_PACR, pacr.value); + + oo.value = in32(OCB_OCICHSW); + oo.fields.plbarb_lockerr = 1; + out32(OCB_OCICHSW, oo.value); +} + + +#if PPC405_MMU_SUPPORT + +#include "ppc405_mmu.h" + +// MMU regions +// +// The linker script provides a standard set of symbols that define the base +// address and size of each expected section. Any section with a non-0 size +// will be mapped in the MMU using protection attributes appropriate for the +// section. All sections requiring different MMU attributes must be +// 1KB-aligned. The OCI control register space is fixed and also mapped by +// the same mechanism. +// +// By default, caching is enabled for all sections other than the sections +// explicitly cache-inhibited. Configuration options are provided to disable +// caching of text, data and both. Note that sections that (may) contain code +// and data will be marked cache-inhibited if either text or data is globally +// configured as cache-inhibited. Also note that "writethrough" can only be +// defined on cacheable data sections. + +#ifdef CACHE_INHIBIT_ALL +#define CACHE_INHIBIT_TEXT 1 +#define CACHE_INHIBIT_DATA 1 +#endif + +#if CACHE_INHIBIT_TEXT +#define TEXT_CACHEABILITY_FLAG TLBLO_I +#else +#define TEXT_CACHEABILITY_FLAG 0 +#endif + +#if CACHE_INHIBIT_DATA +#define DATA_CACHEABILITY_FLAG TLBLO_I +#define WRITETHROUGH_FLAG 0 +#else +#define DATA_CACHEABILITY_FLAG 0 +#define WRITETHROUGH_FLAG TLBLO_W +#endif + + +// This structure contains all of the fields necessary to create a MMU +// mapping. + +typedef struct { + SsxAddress base; + size_t size; + uint32_t tlbhi_flags; + uint32_t tlblo_flags; + Ppc405MmuMap* map; +} MmuRegion; + +// The section table along with (default) MMU characteristics. Global +// Ppc405MmuMap variables are defined for certain sections so that those +// mappings may be later modified. + +Ppc405MmuMap G_ex_free_mmu_map; +Ppc405MmuMap G_applet0_mmu_map; +Ppc405MmuMap G_applet1_mmu_map; + +static const MmuRegion mmu_regions[] = { + + {(SsxAddress)&_TEXT0_SECTION_BASE, + (size_t)&_TEXT0_SECTION_SIZE, + 0, TEXT_CACHEABILITY_FLAG | TLBLO_EX, 0} , + + {(SsxAddress)&_TEXT1_SECTION_BASE, + (size_t)&_TEXT1_SECTION_SIZE, + 0, TEXT_CACHEABILITY_FLAG | TLBLO_EX, 0} , + + {(SsxAddress)&_RODATA_SECTION_BASE, + (size_t)&_RODATA_SECTION_SIZE, + 0, DATA_CACHEABILITY_FLAG, 0} , + + {(SsxAddress)&_NONCACHEABLE_RO_SECTION_BASE, + (size_t)&_NONCACHEABLE_RO_SECTION_SIZE, + 0, TLBLO_I, 0} , + + {(SsxAddress)&_NONCACHEABLE_SECTION_BASE, + (size_t)&_NONCACHEABLE_SECTION_SIZE, + 0, TLBLO_I | TLBLO_WR, 0} , + + {(SsxAddress)&_WRITETHROUGH_SECTION_BASE, + (size_t)&_WRITETHROUGH_SECTION_SIZE, + 0, DATA_CACHEABILITY_FLAG | WRITETHROUGH_FLAG | TLBLO_WR, 0} , + + {(SsxAddress)&_DATA_SECTION_BASE, + (size_t)&_DATA_SECTION_SIZE, + 0, DATA_CACHEABILITY_FLAG | TLBLO_WR, 0} , + + {(SsxAddress)&_EX_FREE_SECTION_BASE, + (size_t)&_EX_FREE_SECTION_SIZE, + 0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_EX | TLBLO_WR, + &G_ex_free_mmu_map}, + + {(SsxAddress)&_APPLET0_SECTION_BASE, + (size_t)&_APPLET0_SECTION_SIZE, + 0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_WR | TLBLO_EX, + &G_applet0_mmu_map}, + + {(SsxAddress)&_APPLET1_SECTION_BASE, + (size_t)&_APPLET1_SECTION_SIZE, + 0, DATA_CACHEABILITY_FLAG | TEXT_CACHEABILITY_FLAG | TLBLO_WR | TLBLO_EX, + &G_applet1_mmu_map}, + + {(SsxAddress)OCI_REGISTER_SPACE_BASE, + (size_t)OCI_REGISTER_SPACE_SIZE, + 0, TLBLO_WR | TLBLO_I | TLBLO_G, 0} , +}; + +/// PgP MMU setup +/// +/// Run down the mmu_regions[] array and map all regions with non-0 sizes. +/// These are direct maps, setting the effective address to the physical +/// address. Once the MMU is set up MMU protection is enabled. +/// +/// Any OCC mappings of PBA space will have to be done elsewhere, as these +/// memory areas are controlled by pHyp, and the product firmware has no plans +/// to access main memory from the OCC. + +static void +pgp_mmu_setup() +{ + int i, regions; + + ppc405_mmu_reset(); + + regions = sizeof(mmu_regions) / sizeof(MmuRegion); + for (i = 0; i < regions; i++) { + if (mmu_regions[i].size != 0) { + ppc405_mmu_map(mmu_regions[i].base, + mmu_regions[i].base, + mmu_regions[i].size, + mmu_regions[i].tlbhi_flags, + mmu_regions[i].tlblo_flags, + mmu_regions[i].map); + } + } + + ppc405_mmu_start(); +} + +#endif /* PPC405_MMU_SUPPORT */ + + +// I/O Initialization +// +// Initialize the SSX/Simics/Verification Serial I/O channels. This is done +// early in the initialization to allow initialization code to use printk(). +// If the application does not select one of the I/O methods then 'ssxout' +// defaults to the NULL stream and 'stdin', 'stdout' and 'stderr' are +// undefined. + +#if USE_TRACE_IO || USE_EPM_IO + +WrappingStream G_ssxout +SECTION_ATTRIBUTE(".noncacheable") = {{0}}; + +uint8_t G_ssxout_buffer[SSXOUT_TRACE_BUFFER_SIZE] +SECTION_ATTRIBUTE(".noncacheable") = {0}; + +#endif // USE_TRACE_IO || USE_EPM_IO + +static void +io_setup() +{ + //NB: These I/O options are listed in priority order - multiple options may + //be selected. +#if USE_TRACE_IO + + // If the application chooses to use trace buffer output, the application + // must define SSXOUT_TRACE_BUFFER_SIZE, and all output streams are merged + // into a single trace buffer which locks low-level file operations in an + // SSX_CRITICAL critical secton. + + /// \todo Split trace I/O mode into multiple streams + + wrapping_stream_create(&G_ssxout, &G_ssxout_buffer, + SSXOUT_TRACE_BUFFER_SIZE, + SSX_FILE_OP_LOCK_CRITICAL); + + stdout = (FILE *)(&G_ssxout); + stderr = (FILE *)(&G_ssxout); + ssxout = (FILE *)(&G_ssxout); + +#elif USE_EPM_IO + + linear_stream_create(&G_ssxout, &G_ssxout_buffer, + SSXOUT_TRACE_BUFFER_SIZE, + SSX_FILE_OP_LOCK_CRITICAL); + + stdout = (FILE *)(&G_ssxout); + stderr = (FILE *)(&G_ssxout); + ssxout = (FILE *)(&G_ssxout); + +#elif USE_RTX_IO + + rtx_stdin_create(&rtx_stdin); + rtx_stdout_create(&rtx_stdout); + rtx_stderr_create(&rtx_stderr); + + stdin = (FILE *)(&rtx_stdin); + stdout = (FILE *)(&rtx_stdout); + stderr = (FILE *)(&rtx_stderr); + ssxout = (FILE *)(&rtx_stdout); + + printf("Initialize the RTX stdio.\n"); + printf("RTX stdin is not implemented.\n"); + +#elif USE_SIMICS_IO + + simics_stdin_create(&simics_stdin); + simics_stdout_create(&simics_stdout); + simics_stderr_create(&simics_stderr); + + stdin = (FILE *)(&simics_stdin); + stdout = (FILE *)(&simics_stdout); + stderr = (FILE *)(&simics_stderr); + ssxout = (FILE *)(&simics_stdout); + +#endif // I/O Configuration +} + + +/// PgP environment initial setup. +/// +/// This is setup common to all PgP applications. This setup takes place +/// during boot, before main() is called. + +void +__pgp_setup() +{ + // All OCB interrupts are masked. The SSX/PPC405 Boot code masks PPC405 + // PIT, FIT, and Watchdog interrupts. All interrupts are also initially + // set up as noncritical, non-debugged, edge-triggered, active-high, and + // their status is cleared. This clarifies IPL debugging as it eliminates + // spurious "asserted" interrupts until the firmware comes in and actually + // sets up the interrupt. + + out32(OCB_OIMR0, 0xffffffff); /* Masked */ + out32(OCB_OIMR1, 0xffffffff); + out32(OCB_OITR0, 0xffffffff); /* Edge */ + out32(OCB_OITR1, 0xffffffff); + out32(OCB_OIEPR0, 0xffffffff); /* Active High */ + out32(OCB_OIEPR1, 0xffffffff); + out32(OCB_OCIR0, 0); /* Noncritical */ + out32(OCB_OCIR1, 0); + out32(OCB_OISR0_AND, 0); /* Clear Status */ + out32(OCB_OISR1_AND, 0); + out32(OCB_OUDER0, 0); /* No Unconditional Debug Event */ + out32(OCB_OUDER1, 0); + out32(OCB_ODHER0, 0); /* No Debug Halt Event */ + out32(OCB_ODHER1, 0); + + // Setup requires SCOM, which requires a timeout. Therefore we need to set + // up a default timebase frequency, which may be overridden during + // ssx_initialize(). + + __ssx_timebase_frequency_hz = 600000000; + __ssx_timebase_frequency_khz = 600000; + __ssx_timebase_frequency_mhz = 600; + + // Set up I/O. This is done early in the initialization so that + // initialization drivers can use printk(). + + io_setup(); + + // Cache the device identification and chip configuration + _pgp_get_ids(); + _pgp_get_chip_configuration(); + + // Set up the PLB arbiter + + plb_arbiter_setup(); + + // If the MMU is enabled the base image MMU programming is set up, and the + // MMU is activated. + +#if PPC405_MMU_SUPPORT + pgp_mmu_setup(); +#endif + + // The PgP Async drivers are initialized. + + async_initialize(); +} diff --git a/src/ssx/pgp/pgp_irq.h b/src/ssx/pgp/pgp_irq.h new file mode 100755 index 0000000..f45ed52 --- /dev/null +++ b/src/ssx/pgp/pgp_irq.h @@ -0,0 +1,252 @@ +#ifndef __PGP_IRQ_H__ +#define __PGP_IRQ_H__ + +// $Id: pgp_irq.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_irq.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_irq.h +/// \brief PPC405-PgP Interrupt handling for SSX +/// +/// The PgP interrupt controller supports a maximum of 64 interrupts, split +/// into 2 x 32-bit non-cascaded interrupt controllers with simple OR +/// combining of the interrupt signals. +/// +/// The PGP interrupt controller allows interrupt status to be set directly by +/// software, as well as providing a mode that causes an enabled pending +/// interrupt to trigger an Unconditional Debug Event. The PGP interrupt +/// controller contains a 'mask' register, unlike other 405 interrupt +/// controllers that have an 'enable' register. The PgP mask and status +/// registers also have atomic AND/OR function so that it is never necessary +/// to enter a critical section to enable/disable/clear interrupts and +/// interrupt status. + +#include "pgp_common.h" +#include "ocb_register_addresses.h" + +#ifndef __ASSEMBLER__ + +/// Enable an interrupt by clearing the mask bit. + +UNLESS__PPC405_IRQ_CORE_C__(extern) +inline void +ssx_irq_enable(SsxIrqId irq) +{ + out32(OCB_OIMR_AND(irq), ~PGP_IRQ_MASK32(irq)); +} + + +/// Disable an interrupt by setting the mask bit. + +UNLESS__PPC405_IRQ_CORE_C__(extern) +inline void +ssx_irq_disable(SsxIrqId irq) +{ + out32(OCB_OIMR_OR(irq), PGP_IRQ_MASK32(irq)); +} + + +/// Clear interrupt status with an AND mask. Only meaningful for +/// edge-triggered interrupts. + +UNLESS__PPC405_IRQ_CORE_C__(extern) +inline void +ssx_irq_status_clear(SsxIrqId irq) +{ + out32(OCB_OISR_AND(irq), ~PGP_IRQ_MASK32(irq)); +} + + +/// Get IRQ status as a 0 or non-0 integer + +UNLESS__PPC405_IRQ_CORE_C__(extern) +inline int +ssx_irq_status_get(SsxIrqId irq) +{ + return (in32(OCB_OISR(irq)) & PGP_IRQ_MASK32(irq)) != 0; +} + + +/// Set or clear interrupt status explicitly. + +UNLESS__PPC405_IRQ_CORE_C__(extern) +inline void +ssx_irq_status_set(SsxIrqId irq, int value) +{ + if (value) { + out32(OCB_OISR_OR(irq), PGP_IRQ_MASK32(irq)); + } else { + out32(OCB_OISR_AND(irq), ~PGP_IRQ_MASK32(irq)); + } +} + + +void +ssx_irq_debug_set(SsxIrqId irq, int value); + +#endif /* __ASSEMBLER__ */ + +/// \page pgp_irq_macros PgP IRQ API Assembler Macros +/// +/// These macros encapsulate the SSX API for the PgP interrupt +/// controller. These macros require 2 scratch registers in addition to the \c +/// irq parameter register passed into the handler from SSX interrupt +/// dispatch. These macros also modift CR0. +/// +/// \arg \c rirq A register that holds the \c irq parameter passed to +/// the handler from SSX interrupt dispatch. This register is not +/// modified. +/// \arg \c rmask A scratch register - At the end of macro execution this +/// register contains the 32-bit mask form of the irq. +/// +/// \arg \c raddr A scratch register - At the end of macro execution this +/// register holds the address of the interrupt +/// controller facility that implements the action. +/// +/// \arg \c imm An immediate (0/non-0) value for certain macros. +/// +/// Forms: +/// +/// \b _ssx_irq_enable \a rirq, \a rmask, \a raddr - Enable an \c irq. \n +/// \b _ssx_irq_disable \a rirq, \a rmask, \a raddr - Disable an \c irq. \n +/// \b _ssx_irq_status_clear \a rirq, \a rmask, \a raddr - Clear \c irq +/// interrupt status. \n +/// \b _ssx_irq_status_set \a rirq, \a rmask, \a raddr, \a imm - Set \c irq status +/// with an immediate (0/non-0) value. \n +/// +/// \todo Once the logic design is locked down, revisit whether these macros +/// (and C-code versions) can be implemented without branching. This could be +/// done in theory by converting bit 26 into the byte offset between addresses +/// in interupt controller 0 and interrupt controller 1 - assuming the +/// distances are all the same power-of-two. +/// +/// \cond + +// IRQ numbers are in the range 0..63. IRQs are converted to the 32-bit +// residue used to compute the mask. CR0 is set as a test of IRQ > 32 - the +// register \c raddr is used as scratch for these computations. Hopefully the +// local labels 888 and 999 are unique enough. + +// Register names must be compared as strings - e.g., %r0 is not +// a symbol, it is converted to "0" by the assembler. + +#ifdef __ASSEMBLER__ + + .macro .two_unique, ra, rb + .ifnc \ra, \rb + .exitm + .endif + .error "Both register arguments must be unique" + .endm + + + .macro .three_unique, ra, rb, rc + .ifnc \ra, \rb + .ifnc \rb, \rc + .ifnc \ra, \rc + .exitm + .endif + .endif + .endif + .error "All three register arguments must be unique" + .endm + + + .macro _pgp_irq_or_mask, rirq:req, rmask:req + .two_unique \rirq, \rmask + lis \rmask, 0x8000 + srw \rmask, \rmask, \rirq + .endm + + .macro _pgp_irq_and_mask, rirq:req, rmask:req + .two_unique \rirq, \rmask + _pgp_irq_or_mask \rirq, \rmask + not \rmask, \rmask + .endm + + + .macro _ssx_irq_enable, rirq:req, rmask:req, raddr:req + .three_unique \rirq, \rmask, \raddr + + andi. \raddr, \rirq, 0x20 + clrlwi \raddr, \rirq, 27 + _pgp_irq_and_mask \raddr, \rmask + bne- 888f + _stwi \rmask, \raddr, OCB_OIMR0_AND + b 999f +888: + _stwi \rmask, \raddr, OCB_OIMR1_AND +999: + eieio + .endm + + + .macro _ssx_irq_disable, rirq:req, rmask:req, raddr:req + .three_unique \rirq, \rmask, \raddr + + andi. \raddr, \rirq, 0x20 + clrlwi \raddr, \rirq, 27 + _pgp_irq_or_mask \raddr, \rmask + bne- 888f + _stwi \rmask, \raddr, OCB_OIMR0_OR + b 999f +888: + _stwi \rmask, \raddr, OCB_OIMR1_OR +999: + eieio + .endm + + + .macro _ssx_irq_status_clear, rirq:req, rmask:req, raddr:req + .three_unique \rirq, \rmask, \raddr + + andi. \raddr, \rirq, 0x20 + clrlwi \raddr, \rirq, 27 + _pgp_irq_and_mask \raddr, \rmask + bne- 888f + _stwi \rmask, \raddr, OCB_OISR0_AND + b 999f +888: + _stwi \rmask, \raddr, OCB_OISR1_AND +999: + eieio + .endm + + + .macro _ssx_irq_status_set, rirq:req, rmask:req, raddr:req, imm:req + .three_unique \rirq, \rmask, \raddr + + andi. \raddr, \rirq, 0x20 + clrlwi \raddr, \rirq, 27 + + .if \imm + _pgp_irq_or_mask \raddr, \rmask + bne- 888f + _stwi \rmask, \raddr, OCB_OISR0_OR + b 999f +888: + _stwi \rmask, \raddr, OCB_OISR1_OR + + .else + + _pgp_irq_and_mask \raddr, \rmask + bne- 888f + _stwi \rmask, \raddr, OCB_OISR0_AND + b 999f +888: + _stwi \rmask, \raddr, OCB_OISR1_AND + .endif + +999: + eieio + .endm + +#endif /* __ASSEMBLER__ */ + +/// \endcond + +#endif /* __PGP_IRQ_H__ */ diff --git a/src/ssx/pgp/pgp_irq_init.c b/src/ssx/pgp/pgp_irq_init.c new file mode 100755 index 0000000..6719766 --- /dev/null +++ b/src/ssx/pgp/pgp_irq_init.c @@ -0,0 +1,155 @@ +// $Id: pgp_irq_init.c,v 1.2 2014/02/03 01:30:35 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_irq_init.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_irq_init.c +/// \brief PGP IRQ initialization code for SSX +/// +/// The entry points in this file are initialization rotines that could be +/// eliminated/deallocated by the application to free up storage if they are +/// no longer needed after initialization. + +#include "ssx.h" + +/// Define the polarity and trigger condition for an interrupt. +/// +/// It is up to the application to take care of any side effects that may +/// occur from programming or reprogramming the interrupt controller. For +/// example, changing edge/level sensitivity or active level may set or clear +/// interrupt status in the controller. +/// +/// Note that SSX allows this API to be called from any context, and changes +/// to the interrupt controller are made from an SSX_CRITICAL critical +/// section. +/// +/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_ARGUMENT_IRQ_SETUP One or more arguments are invalid, +/// including an invalid \a irq, or invalid \a polarity or \a trigger parameters. + +int +ssx_irq_setup(SsxIrqId irq, + int polarity, + int trigger) +{ + SsxMachineContext ctx; + uint32_t oitr, oeipr; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(!PGP_IRQ_VALID(irq) || + !((polarity == SSX_IRQ_POLARITY_ACTIVE_HIGH) || + (polarity == SSX_IRQ_POLARITY_ACTIVE_LOW)) || + !((trigger == SSX_IRQ_TRIGGER_LEVEL_SENSITIVE) || + (trigger == SSX_IRQ_TRIGGER_EDGE_SENSITIVE)), + SSX_INVALID_ARGUMENT_IRQ_SETUP); + } + + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + + oeipr = in32(OCB_OIEPR(irq)); + if (polarity == SSX_IRQ_POLARITY_ACTIVE_HIGH) { + out32(OCB_OIEPR(irq), oeipr | PGP_IRQ_MASK32(irq)); + } else { + out32(OCB_OIEPR(irq), oeipr & ~PGP_IRQ_MASK32(irq)); + } + + oitr = in32(OCB_OITR(irq)); + if (trigger == SSX_IRQ_TRIGGER_EDGE_SENSITIVE) { + out32(OCB_OITR(irq), oitr | PGP_IRQ_MASK32(irq)); + } else { + out32(OCB_OITR(irq), oitr & ~PGP_IRQ_MASK32(irq)); + } + + ssx_critical_section_exit(&ctx); + + return SSX_OK; +} + + +/// (Re)define the IRQ handler and priority for an interrupt. +/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors +/// +/// Note that SSX allows this API to be called from any context, and changes +/// to the interrupt controller are made from an SSX_CRITICAL critical +/// section. +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_ARGUMENT_IRQ_HANDLER One or more arguments are +/// invalid, including an invalid \a irq, a null (0) \a handler, +/// or invalid \a priority. + +int +ssx_irq_handler_set(SsxIrqId irq, + SsxIrqHandler handler, + void *arg, + int priority) +{ + SsxMachineContext ctx; + uint32_t ocir; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(!PGP_IRQ_VALID(irq) || + (handler == 0) || + !((priority == SSX_NONCRITICAL) || + (priority == SSX_CRITICAL)), + SSX_INVALID_ARGUMENT_IRQ_HANDLER); + } + + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + + ocir = in32(OCB_OCIR(irq)); + if (priority == SSX_CRITICAL) { + out32(OCB_OCIR(irq), ocir | PGP_IRQ_MASK32(irq)); + } else { + out32(OCB_OCIR(irq), ocir & ~PGP_IRQ_MASK32(irq)); + } + + __ppc405_irq_handlers[irq].handler = handler; + __ppc405_irq_handlers[irq].arg = arg; + + ssx_critical_section_exit(&ctx); + + return SSX_OK; +} + + +/// Set or clear interrupt debug mode explicitly. + +void +ssx_irq_debug_set(SsxIrqId irq, int value) +{ + SsxMachineContext ctx; + uint32_t ouder; + + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + + ouder = in32(OCB_OUDER(irq)); + if (value) { + out32(OCB_OUDER(irq), ouder | PGP_IRQ_MASK32(irq)); + } else { + out32(OCB_OUDER(irq), ouder & ~PGP_IRQ_MASK32(irq)); + } + + ssx_critical_section_exit(&ctx); +} + + + + + + + + + + + + + + diff --git a/src/ssx/pgp/pgp_ocb.c b/src/ssx/pgp/pgp_ocb.c new file mode 100755 index 0000000..e39475e --- /dev/null +++ b/src/ssx/pgp/pgp_ocb.c @@ -0,0 +1,335 @@ +// $Id: pgp_ocb.c,v 1.2 2014/02/03 01:30:35 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_ocb.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_ocb.c +/// \brief OCB-related drivers for PgP + +#include "ssx.h" + +//use compile-time default in case the OCB timer is never used -- grm +unsigned int g_ocb_timer_divider = OCB_TIMER_DIVIDER_DEFAULT; + +/// Reset an OCB timer +/// +/// \param timer A valid OCB timer index +/// +/// \param auto_reload A non-0 value indicates to run the timer in auto-reload +/// mode. +/// +/// \param timeout_ns The timeout specified in nanoseconds. The actual timeout +/// will be rounded down to the underlying timer tick, with a minimum 1 tick +/// timeout. However if the \a timeout_ns argument is explicity 0, then the +/// timer wil be initialized with a 0 timeout, effectively disabling the +/// timer. +/// +/// Reseting an OCB timer means rewriting the timer control register with a +/// potentially new auto-reload enable and new timeout value. This API also +/// clears any pending timer interrupt status. +/// +/// \retval 0 Success +/// +/// \retval -OCB_INVALID_ARGUMENT_TIMER Causes include illegal timer +/// numbers and illegal or unrepresntable timeouts. + +// Note that OCB_TIMER_FREQUENCY_HZ is in the range of 1-2 MHz. + +int +ocb_timer_reset(int timer, + int auto_reload, + int timeout_ns) +{ + ocb_otrn_t otr; + int ticks; + + //printk("ocb_timer_reset(%d, %d, %d)\n", + // timer, auto_reload, timeout_ns); + + if (timeout_ns != 0) { + ticks = MAX(1, timeout_ns / (1000000000 / OCB_TIMER_FREQUENCY_HZ)); + } else { + ticks = 0; + } + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((timer < 0) || + (timer >= OCB_TIMERS) || + (timeout_ns < 0) || + (ticks != ((uint16_t)ticks)), + OCB_INVALID_ARGUMENT_TIMER); + } + + otr.value = 0; + + otr.fields.timeout = 1; + otr.fields.control = 1; + otr.fields.auto_reload = (auto_reload != 0); + otr.fields.timer = ticks; + + out32(OCB_OTRN(timer), otr.value); + + return 0; +} + + +/// Set up an OCB timer and interrupt handler +/// +/// \param timer A valid OCB timer index +/// +/// \param auto_reload A non-0 value indicates to run the timer in auto-reload +/// mode. +/// +/// \param timeout_ns The timeout specified in nanoseconds. The actual timeout +/// will rounded down to the underlying timer tick, with a minimum 1 tick +/// timeout. However if the \a timeout_ns argument is explicity 0, then the +/// timer wil be initialized with a 0 timeout, effectively disabling the +/// timer. +/// +/// \param handler The interrupt handler for the timer interrupt +/// +/// \param arg The private argument of the interrupt handler +/// +/// \param priority The SSX/PPC405 interrupt priority to assign to the +/// interrupt. +/// +/// This API sets up and starts the timer and unmasks the timer +/// interrupt. Once set up, the timer can be reset using ocb_timer_reset(). As +/// a fine point of the specification, if a timer interrupt is already pending +/// when this API is invoked then that interrupt will be cleared. Only the +/// next interrupt (corresponding to the new programming) will be serviced by +/// the newly installed handler. +/// +/// Note that the interrupt handler is responsible for clearing the timer +/// interrupt status. An API ocb_timer_status_clear() is available for this. +/// +/// \retval 0 Success +/// +/// \retval -OCB_INVALID_ARGUMENT_TIMER Causes include illegal timer +/// numbers and illegal or unrepresntable timeouts. +/// +/// Other errors may be returned by the underlying calls to SSX routines that +/// set up interrupts. + +int +ocb_timer_setup(int timer, + int auto_reload, + int timeout_ns, + SsxIrqHandler handler, + void *arg, + int priority) +{ + int rc; + tpc_hpr2_t l_hpr2; + + do + { + //Read Hang Pulse Register 2 to get the log base 2 of the ocb clock divider -- grm + rc = getscom(TPC_HPR2, &l_hpr2.value); + if(rc) + { + break; + } + + g_ocb_timer_divider = 1 << l_hpr2.fields.hang_pulse_reg; + + //printk("ocb_timer_setup(%d, %d, %d, %p, %p, %d)\n", + // timer, auto_reload, timeout_ns, + // handler, arg, priority); + + ssx_irq_disable(PGP_IRQ_OCC_TIMER0 + timer); + + ssx_irq_setup(PGP_IRQ_OCC_TIMER0 + timer, + SSX_IRQ_POLARITY_ACTIVE_HIGH, + SSX_IRQ_TRIGGER_LEVEL_SENSITIVE); + + ssx_irq_handler_set(PGP_IRQ_OCC_TIMER0 + timer, + handler, + arg, + priority); + + rc = ocb_timer_reset(timer, auto_reload, timeout_ns); + + ssx_irq_enable(PGP_IRQ_OCC_TIMER0 + timer); + }while(0); + + return rc; +} + + +/// Generate an core interrupt via the PSI Host Bridge +/// +/// Setting OCB_OCCMISC.core_ext_int to 1 causes a wire to pulse to the PSI +/// Host Bridge to allow the presentation of an external interrupt to a core +/// thread. The core thread to be interrupted is controlled by the XIVR - OCC +/// register, SCOM 02010916. Normally the hypervisor will set up the PSI Host +/// Bridge. This procedure allows OCC to send an interrupt to the hypervisor. +/// +/// \retval 0 Success + +// The interrupt is generated by causing a 0->1 transation on +// OCB_OCCMISC.core_ext_intr. This is implemented here using the WAND/WOR +// forms of the register. + +int +ocb_core_interrupt() +{ + ocb_occmisc_t oo; + + oo.value = 0; + oo.fields.core_ext_intr = 1; + out32(OCB_OCCMISC_AND, ~oo.value); + out32(OCB_OCCMISC_OR, oo.value); + + return 0; +} + + +/// Procedure to setup a linear window on an indirect channel +/// +/// +/// Since the linear window access is restricted to the SRAM region of +/// OCI space, Bits 0:4 of the base parameter are don't care and will be +/// overwritten with b'11000' +/// +/// +/// \todo double check SRAM region restriction +/// +/// \param channel The indirect channel to use, in the range 0..2. +/// +/// \param base The 32-bit PowerBus base address where the block starts. This +/// address must be aligned to the \a log_size. +/// +/// \param log_size The base 2 logarithm of the block size, in bytes. The +/// minimum size is 8B (2**3), the maximum size is 32KB (2**15) +/// +/// +/// \retval 0 Success +/// +/// \retval OCB_INVALID_ARGUMENT_LW_INIT One or more of the parameter +/// restrictions were violated. +/// +/// \retval OCB_SCOM_ERROR An attempt to write a PBA SCOM register to set up +/// the BARs produced a non-zero return code. + +int +ocb_linear_window_initialize(int channel, uint32_t base, int log_size) +{ + uint32_t mask ; + ocb_ocblwcrn_t ocblwcrn; + ocb_ocblwsbrn_t ocblwsbrn; + + // create mask for checking + mask = (0x1ull << log_size) - 1; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((channel < 0) || + (channel > 2) || + (log_size < OCB_LW_LOG_SIZE_MIN) || + (log_size > OCB_LW_LOG_SIZE_MAX) || + ((base & mask) != 0), + OCB_INVALID_ARGUMENT_LW_INIT); + } + + // now invert mask for use in ocb linear window setup + mask = ~mask; + + + // Configure OCB Linear Write Control Register + ocblwcrn.fields.linear_window_enable = 1; + // base 13:28 (16 bits) + ocblwcrn.fields.linear_window_bar = (base >> 3) & 0xFFFF; + // mask 17:28 (12 bits) + ocblwcrn.fields.linear_window_mask = (mask >> 3) & 0xFFF; + out32(OCB_OCBLWCRN(channel), ocblwcrn.value); + + // Configure OCB Linear Window Write Base Register + ocblwsbrn.fields.linear_window_region = 3; // SRAM only + // \todo: Are there constants for the OCI regions? + // base 2:9 (8 bits) + ocblwsbrn.fields.linear_window_base = (base >> 19) & 0xFF; + out32(OCB_OCBLWSBRN(channel), ocblwsbrn.value); + + return 0 ; +} + +/// Procedure to disable a linear window on an indirect channel +/// +/// This procedure will disable the linear window while maintaining +/// the linear_window_bar and linear_window_mask settings +/// +/// \param channel The indirect channel to disable, in the range 0..2. +/// +/// \retval 0 Success +/// +/// \retval OCB_INVALID_ARGUMENT_LW_DISABLE One or more of the parameter +/// restrictions were violated. +/// + +int +ocb_linear_window_disable(int channel) +{ + ocb_ocblwcrn_t ocblwcrn; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((channel < 0) || + (channel > 2), + OCB_INVALID_ARGUMENT_LW_DISABLE); + } + + ocblwcrn.value = in32(OCB_OCBLWCRN(channel)); + // Configure OCB Linear Write Control Register + ocblwcrn.fields.linear_window_enable = 0; + out32(OCB_OCBLWCRN(channel), ocblwcrn.value); + + return 0 ; +} + + +/// Procedure for setting up untrusted mode for an indirect channel +/// +/// Note that the OCC FW is expected to enable the channel for FSP +/// access. As an untrusted master, the FSP cannot configure this +/// in a chip running in trusted mode. The SBE is considered a trusted +/// master. +/// +/// +/// \param channel The indirect channel to use, in the range 0..2 +/// Note that this bit is not used for indirect channel 3. +/// +/// +/// \param allow_untrusted Enable untrusted PIB masters +/// access to the indirect channel being configured. If allow_untrusted is +/// not enabled and the chip is running in trusted mode, then any untrusted +/// PIB master will get an offline return code when attempting to write +/// the indirect channel. 0 = Disable, 1 = Enable +/// +/// \retval 0 Success +/// +/// \retval OCB_INVALID_ARGUMENT_UNTRUST One or more of the parameter +/// restrictions were violated. +/// + + +int +ocb_allow_untrusted_initialize(int channel, int allow_untrusted) +{ + ocb_ocbicrn_t ocbicrn; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((channel < 0) || + (channel > 2) || + (allow_untrusted < 0) || + (allow_untrusted > 1), + OCB_INVALID_ARGUMENT_UNTRUST); + } + + // Configure allow_unsecure_pib_masters bit + ocbicrn.fields.allow_unsecure_pib_masters = allow_untrusted; + out32(OCB_OCBICRN(channel), ocbicrn.value); + + return 0 ; +} diff --git a/src/ssx/pgp/pgp_ocb.h b/src/ssx/pgp/pgp_ocb.h new file mode 100755 index 0000000..fd36c9a --- /dev/null +++ b/src/ssx/pgp/pgp_ocb.h @@ -0,0 +1,88 @@ +#ifndef __PGP_OCB_H__ +#define __PGP_OCB_H__ + +// $Id: pgp_ocb.h,v 1.2 2014/02/03 01:30:35 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_ocb.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_ocb.h +/// \brief OCB unit header. Local and mechanically generated macros and APIs. + +#include "ssx.h" +#include "ppc32.h" + +#include "pgp_common.h" +#include "ocb_register_addresses.h" +#include "ocb_firmware_registers.h" + +#include "ppc405_irq.h" + +#define OCB_TIMER0 0 +#define OCB_TIMER1 1 + +#define OCB_TIMERS 2 + +#define OCB_TIMER_ONE_SHOT 0 +#define OCB_TIMER_AUTO_RELOAD 1 + +#define OCB_LW_LOG_SIZE_MIN 3 +#define OCB_LW_LOG_SIZE_MAX 15 + +#define OCB_INVALID_ARGUMENT_TIMER 0x00622001 +#define OCB_INVALID_ARGUMENT_LW_INIT 0x00622002 +#define OCB_INVALID_ARGUMENT_LW_DISABLE 0x00622003 +#define OCB_INVALID_ARGUMENT_UNTRUST 0x00622004 + +#ifndef __ASSEMBLER__ + +int +ocb_timer_reset(int timer, + int auto_reload, + int timeout_ns); + +#ifdef OCC +int +ocb_timer_setup(int timer, + int auto_reload, + int timeout_ns, + SsxIrqHandler handler, + void *arg, + int priority) INIT_SECTION; +#else +int +ocb_timer_setup(int timer, + int auto_reload, + int timeout_ns, + SsxIrqHandler handler, + void *arg, + int priority); +#endif + +/// Clear OCB timer status based on the IRQ +/// +/// This API can be called from OCB timer interrupt handlers, using the IRQ +/// provided to the handler. No error checks are provided. + +static inline void +ocb_timer_status_clear(SsxIrqId irq) +{ + out32(OCB_OTRN(irq - PGP_IRQ_OCC_TIMER0), OCB_OTRN_TIMEOUT); +} + +int +ocb_linear_window_initialize(int channel, uint32_t base, int log_size); + +int +ocb_linear_window_disable(int channel); + +int +ocb_allow_untrusted_initialize(int channel, int allow_untrusted); + + +#endif /* __ASSEMBLER__ */ + +#endif /* __PGP_OCB_H__ */ diff --git a/src/ssx/pgp/pgp_pba.c b/src/ssx/pgp/pgp_pba.c new file mode 100755 index 0000000..0f5d2d9 --- /dev/null +++ b/src/ssx/pgp/pgp_pba.c @@ -0,0 +1,460 @@ +// $Id: pgp_pba.c,v 1.2 2014/02/03 01:30:35 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_pba.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_pba.c +/// \brief procedures for pba setup and operation. + +#include "ssx.h" +#include "pgp_pba.h" +#include "pgp_pmc.h" +#include "pgp_common.h" +#include "polling.h" + + +// Internal API to set up a PBA BAR + +static int +pba_bar_set(int idx, uint64_t pb_base, uint8_t pb_scope) +{ + int rc ; + pba_barn_t bar ; + + bar.fields.cmd_scope = pb_scope ; + bar.fields.addr = pb_base >> PBA_LOG_SIZE_MIN ; + + rc = putscom(PBA_BARN(idx), bar.value); + + return rc ; +} + + +// Internal API to set up a PBA BAR Mask. The mask covers bits 23:43, address +// bits 44:63 are always allowed. + +static int +pba_barmask_set(int idx, uint64_t mask) +{ + int rc ; + pba_barmskn_t barmask ; + + barmask.value = mask & 0x000001FFFFF00000ull; + + rc = putscom(PBA_BARMSKN(idx), barmask.value); + + return rc ; +} + + +/// Procedure to allocate a PowerBus address block using the bridge. +/// +/// \param idx The BAR set to use, in the range 0..3. +/// +/// \param base The 50-bit PowerBus base address where the block starts. This +/// address must be aligned to the \a log_size. +/// +/// \param log_size The base 2 logarithm of the block size, in bytes. The +/// minimum size is 1MB (2**20), the maximum size is 2TB (2**41) +/// +/// This is a validation/test procedure only, since setting up the PBA BARs is +/// normally reserved to pHyp and FSP. If the MMU is enabled and the PBA +/// mapping will be referenced by the 405, then an MMU mapping will also have +/// to be created (separately) for the block. +/// +/// This procedure is not the complete setup for large memory areas. Memory +/// areas that require the extended address will have to set that up +/// separately. +/// +/// \retval 0 Success +/// +/// \retval PBA_INVALID_ARGUMENT_BARSET One or more of the parameter +/// restrictions were violated. +/// +/// \retval PBA_SCOM_ERROR1 or PBA_SCOM_ERROR2 An attempt to write a PBA SCOM +/// register to set up the BARs produced a non-zero return code. + +int +pba_barset_initialize(int idx, uint64_t base, int log_size) +{ + uint64_t mask ; + + mask = (0x1ull << log_size) - 1; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((idx < 0) || + (idx > 3) || + (log_size < PBA_LOG_SIZE_MIN) || + (log_size > PBA_LOG_SIZE_MAX) || + ((base & mask) != 0), + PBA_INVALID_ARGUMENT_BARSET); + } + + if (pba_bar_set(idx, base, PBA_POWERBUS_COMMAND_SCOPE_DEFAULT)) { + SSX_ERROR(PBA_SCOM_ERROR1); + } + if (pba_barmask_set(idx, mask)) { + SSX_ERROR(PBA_SCOM_ERROR2); + } + + return 0 ; +} + + +// polling() function for PBA Slave reset +// +// Slave reset for PBA is a complex issue, especially in cases where the +// entity requesting the reset may be executing from main memory, i.e. +// continuing to read to or write from the slave being reset. To work around +// potential issues if the 405 is attempting to reset its own slave, the code +// that polls for reset is PowerBus cache-line aligned, and we re-hit the +// reset button each time we get an unsuccessful poll for the reset being +// done. This should guarantee that the slave will go to reset status as soon +// as any PowerBus blockages (if any) clear and the master stops either +// reading or writing the slave port. For details see HW228485. +int +_pba_slave_reset_poll(void* arg, int* done) ALIGNED_ATTRIBUTE(128); + +int +_pba_slave_reset_poll(void* arg, int* done) +{ + int id; + pba_slvrst_t psr; + + id = (int)arg; + + psr.value = 0; + psr.fields.set = PBA_SLVRST_SET(id); + out64(PBA_SLVRST, psr.value); + + psr.value = in64(PBA_SLVRST); + *done = !(psr.fields.in_prog & PBA_SLVRST_IN_PROG(id)); + + return 0; +} + + +/// Reset a PBA slave with explicit timeout. +/// +/// \param id A PBA slave id in the range 0..3 +/// +/// \param timeout A value of SsxInterval type. The special value +/// SSX_WAIT_FOREVER indicates no timeout. +/// +/// \param sleep A value of SsxInterval type. Callers using the explicit +/// timeout form can request that the thread sleeps between polls; See +/// documentation for the polling() API. +/// +/// This form of pba_slave_reset() gives the caller control over timeouts, +/// sleeping and error handling. +/// +/// \retval 0 Success +/// +/// \retval -PBA_INVALID_ARGUMENT_RESET The slave \a id parameter +/// is invalid. +/// +/// \retval -PBA_SLVRST_TIMED_OUT1 The procedure timed out waiting for the PBA +/// to reset the slave. + + +int +_pba_slave_reset(int id, SsxInterval timeout, SsxInterval sleep) +{ + int rc, closureRc; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((id < 0) || (id >= PBA_SLAVES), + PBA_INVALID_ARGUMENT_RESET); + } + + rc = polling(&closureRc, _pba_slave_reset_poll, (void*)id, timeout, sleep); + if (rc == POLLING_TIMEOUT) { + rc = -PBA_SLVRST_TIMED_OUT1; + } + + return rc; +} + + +/// Reset a PBA slave with a default timeout +/// +/// \param id A PBA slave id in the range 0..3 +/// +/// PBA slaves must be reset before being reprogrammed. Resetting a slave +/// also flushes any write buffers and invalidates any read buffers associated +/// with the slave. This procedure is for initialization/bringup/test only; +/// it has a non-deterministic run time due to the PowerBus so should not be +/// run as part of a hard real-time loop. +/// +/// \retval 0 Success +/// +/// \retval -SSX_INVALID_ARGUMENT_PBA_RESET The slave \a id parameter is +/// invalid. +/// +/// \retval -PBA_SLVRST_TIMED_OUT2 The procedure timed out waiting for the PBA +/// to reset the slave. + +int +pba_slave_reset(int id) +{ + int rc; + + rc = _pba_slave_reset(id, PBA_SLAVE_RESET_TIMEOUT, 0); + if (rc) { + SSX_ERROR(PBA_SLVRST_TIMED_OUT2); + } + + return rc; +} + + +/// Configure the PBAX mechanism +/// +/// \param master If non-0, then this OCC will assume the role of the PBAX +/// master processor in the power domain. To avoid PBAX livelock there can +/// only be a single master in any power domain, and only the master is +/// allowed to issue PBAX broadcast transactions. +/// +/// \param node The PBAX Node Id of this OCC +/// +/// \param chip The PBAX Chip Id of this OCC +/// +/// \param group_mask A bit mask indicating the broadcast group(s) (power +/// domain(s)) that this OCC belongs to. +/// +/// This API sets up certain fields of the PBA_XCFG register according to the +/// parameters. Other fields in the register controlling hardware timeouts and +/// performance monitoring are unchanged. +/// +/// \retval 0 Success +/// +/// \retval -PBAX_INVALID_ARGUMENT_CONFIG One of the arguments is +/// not valid for some reason. + +int +pbax_configure(int master, int node, int chip, int group_mask) +{ + pba_xcfg_t pxc; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((node < 0) || + (node >= PBAX_NODES) || + (chip < 0) || + (chip >= PBAX_CHIPS) || + (group_mask < 0) || + (group_mask > PBAX_GROUP_MASK_MAX), + PBAX_INVALID_ARGUMENT_CONFIG); + } + pxc.value = in64(PBA_XCFG); + pxc.fields.reservation_en = (master != 0); + pxc.fields.rcv_nodeid = node; + pxc.fields.rcv_chipid = chip; + pxc.fields.rcv_brdcst_group = group_mask; + out64(PBA_XCFG, pxc.value); + return 0; +} + + +/// Create a PBAX abstract target +/// +/// \param target An uninitialized or otherwise idle PbaxTarget object +/// +/// \param type The transmission type, either PBAX_UNICAST or PBAX_BROADCAST +/// +/// \param scope The PowerBus scope, either PBAX_GROUP or PBAX_SYSTEM +/// +/// \param queue The receive queue index on the target, either 0 or 1 +/// +/// \param node The PBAX Node Id of the target +/// +/// \param chip_or_group Either the PBAX Chip Id of the target (for unicast), +/// or the PBAX Group Id of the target (for broadcast) +/// +/// Create an abstraction of a communication target for PBAX send operations, +/// for use with the _pbax_send() and _pbax_send() APIs. This API has no +/// knowledge of how the PBAX is configured, and therefore accepts all node, +/// chip and broadcast group ids as valid. However this API does assume that +/// all broadcast transactions are "real-time" and require a reservation. +/// +/// \retval 0 Success +/// +/// \retval -PBAX_INVALID_OBJECT The \a target parameter is NULL (0) or +/// otherwise invalid. +/// +/// \retval -PBAX_INVALID_ARGUMENT_TARGET One or more of the arguments +/// is invalid. + +int +pbax_target_create(PbaxTarget* target, + int type, int scope, int queue, + int node, int chip_or_group) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(target == 0, PBAX_INVALID_OBJECT); + SSX_ERROR_IF(((type != PBAX_UNICAST) && (type != PBAX_BROADCAST)) || + ((scope != PBAX_GROUP) && (scope != PBAX_SYSTEM)) || + ((queue < 0) || (queue >= PBAX_QUEUES)), + PBAX_INVALID_ARGUMENT_TARGET); + } + + target->target.value = 0; + target->target.fields.snd_scope = scope; + target->target.fields.snd_qid = queue; + target->target.fields.snd_type = type; + target->target.fields.snd_reservation = (type == PBAX_BROADCAST); + target->target.fields.snd_nodeid = node; + target->target.fields.snd_chipid = chip_or_group; + + return 0; +} + + + +/// Use PBAX to send 64 bits to a target with a caller-specified timeout +/// +/// \param target An abstract PBAX target object +/// +/// \param data The data to send +/// +/// \param timeout The caller's timeout represented as an +/// SsxInterval. Use SSX_WAIT_FOREVER to indicate the caller is willing to +/// wait forever. A \a timeout of 0 indicates that the caller is not +/// willing to wait at all, and the call will either succeed immediately or +/// immediately return -PBAX_TIMEOUT. +/// +/// The PBAX mechanism has a single outgoing channel that must be shared by +/// all processes that need to send messages using PBAX. Since messages sent +/// over PBAX may require an unknown amount of time to complete (due to +/// PowerBus traffic and blockages), this driver implements an agressive +/// policy that allows a sender to initiate a send transaction without waiting +/// for the final completion status. However this opens a window where a +/// subsequent writer may find the PBAX send mechanism already in use. Here +/// the new sender is obligated to busy-wait until the send mechanism is free, +/// as the PBAX send does not include an interrupt notification. +/// +/// This form of the PBAX send operation accepts an explicit \a timeout value +/// as previously described. The timeout represents the amount of time that +/// the caller is willing to wait for a busy PBAX send mechanism to become +/// free. The PBAX hardware also includes mechanisms to time out the hardware +/// and modeably interrupt OCC in the event of lack of progress. +/// +/// <em> This API does not operate in a critical section or enforce any +/// synchronization protocol. Synchronization and software timeout management +/// in the case of multiple senders is the responsibility of the +/// application. </em> +/// +/// Unlike most other driver APIs this API can not be configured to "panic", +/// but instead always terminates with a 0 return code or an error status. +/// +/// \retval 0 Success. Success only means that a transaction was sucessfully +/// initiated on an idle PBAX send machine. +/// +/// \retval -PBAX_TIMEOUT The caller-specified timeout expired before the PBAX +/// send machine became free, but the PBAX send machine does not show error +/// status. +/// +/// \retval -PBAX_SEND_ERROR The PBAXSNDSTAT.snd_error bit is asserted. It +/// is expected that this error will cause the PBA error interrupt to fire - +/// FFDC is collected by the interrupt handler. + +int +_pbax_send(PbaxTarget* target, uint64_t data, SsxInterval timeout) +{ + pba_xsndstat_t pss; + SsxTimebase start; + int rc, timed_out; + + // The PBAX is always polled at least twice to guarantee that we always + // poll once after a timeout - unless the caller explicitly requested a 0 + // timeout. + + start = 0; + timed_out = 0; + do { + pss.words.high_order = in32(PBA_XSNDSTAT); + if (pss.fields.snd_error) { + rc = -PBAX_SEND_ERROR; + break; + } + if (!pss.fields.snd_in_progress) { + rc = 0; + break; + } + if (start == 0) { + start = ssx_timebase_get(); + } + if ((timeout == 0) || timed_out) { + rc = -PBAX_SEND_TIMEOUT; + break; + } + timed_out = + ((timeout != SSX_WAIT_FOREVER) && + ((ssx_timebase_get() - start) > timeout)); + } while (1); + + // Configure the send engine and initiate the write, which is kicked off + // by writing the high-order word of the send data register. + + if (!rc) { + out32(PBA_XSNDTX, target->target.words.high_order); + out32(PBA_XSNDDAT + 4, data & 0xffffffff); + out32(PBA_XSNDDAT, data >> 32); + } + + return rc; +} + + +/// Use PBAX to send 64 bits to a target with a default timeout +/// +/// \param target An abstract PBAX target object +/// +/// \param data The data to send +/// +/// This form of the PBAX send operation uses a default timeout, and may be +/// configured to panic in the event of timeouts or send errors. See +/// _pbax_send() for the specification of the underlying API. +/// +/// <em> This API does not operate in a critical section or enforce any +/// synchronization protocol. Synchronization and software timeout management +/// in the case of multiple senders is the responsibility of the +/// application. </em> +/// +/// \retval 0 Success. Success only means that a transaction was sucessfully +/// initiated on an idle PBAX send machine. +/// +/// \retval -PBAX_TIMEOUT The caller-specified timeout expired before the PBAX +/// send machine became free. +/// +/// \retval -PBAX_SEND_ERROR The PBAXSNDSTAT.snd_error bit is asserted. + +int +pbax_send(PbaxTarget* target, uint64_t data) +{ + int rc; + + rc = _pbax_send(target, data, PBAX_SEND_DEFAULT_TIMEOUT); + if (rc) { + if (rc == -PBAX_SEND_TIMEOUT) { + SSX_ERROR(PBAX_SEND_TIMEOUT); + } else { + SSX_ERROR(PBAX_SEND_ERROR); + } + } + return rc; +} + + + + + + + + + + + + diff --git a/src/ssx/pgp/pgp_pba.h b/src/ssx/pgp/pgp_pba.h new file mode 100755 index 0000000..647c334 --- /dev/null +++ b/src/ssx/pgp/pgp_pba.h @@ -0,0 +1,358 @@ +#ifndef __PGP_PBA_H__ +#define __PGP_PBA_H__ + +// $Id: pgp_pba.h,v 1.2 2014/02/03 01:30:35 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_pba.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_pba.h +/// \brief PBA unit header. Local and mechanically generated macros. + +/// \todo Add Doxygen grouping to constant groups + +#include "pba_register_addresses.h" +#include "pba_firmware_registers.h" + +#define POWERBUS_CACHE_LINE_SIZE 128 +#define LOG_POWERBUS_CACHE_LINE_SIZE 7 + +/// The PBA OCI region is always either 0 or 3 +#define PBA_OCI_REGION 0 + +// It is assumed the the PBA BAR sets will be assigned according to the +// following scheme. There are still many open questions concerning PBA +// setup. + +/// The number of PBA Base Address Registers (BARS) +#define PBA_BARS 4 + +#define PBA_BAR_CHIP 0 +#define PBA_BAR_NODE 2 +#define PBA_BAR_SYSTEM 3 +#define PBA_BAR_CENTAUR 1 + +#define PBA_BAR_OCC 0 /* OCC image (HOMER) */ +#define PBA_BAR_PORE_SLW 2 /* Redundant mapping for SLW offset into HOMER */ + +// Standard PBA slave assignments, set up by FAPI procedure prior to releasing +// OCC from reset. + +/// The number of PBA slaves +#define PBA_SLAVES 4 + +#define PBA_SLAVE_PORE_GPE 0 /* GPE0/1, but only 1 can access mainstore */ +#define PBA_SLAVE_OCC 1 /* 405 I- and D-cache */ +#define PBA_SLAVE_PORE_SLW 2 +#define PBA_SLAVE_OCB 3 + +/// The maximum number of bytes a PBA block-copy engine can transfer at once +#define PBA_BCE_SIZE_MAX 4096 + +/// The base-2 log of the minimum PBA translation window size in bytes +#define PBA_LOG_SIZE_MIN 20 + +/// The base-2 log of the maximum PBA translation window size in bytes +/// +/// Note that windows > 2**27 bytes require the extended address. +#define PBA_LOG_SIZE_MAX 41 + +/// The number of PBA slaves +#define PBA_SLAVES 4 + +/// The number of PBA read buffers +#define PBA_READ_BUFFERS 6 + +/// The number of PBA write buffers +#define PBA_WRITE_BUFFERS 2 + + +//////////////////////////////////// +// Macros for fields of PBA_SLVCTLn +//////////////////////////////////// + +// PBA write Ttypes + +#define PBA_WRITE_TTYPE_DMA_PR_WR 0x0 /// DMA Partial Write +#define PBA_WRITE_TTYPE_LCO_M 0x1 /// L3 LCO for IPL, Tsize denotes chiplet. +#define PBA_WRITE_TTYPE_ATOMIC_RMW 0x2 /// Atomic operations +#define PBA_WRITE_TTYPE_CACHE_INJECT 0x3 /// Cache inject after IPL +#define PBA_WRITE_TTYPE_CI_PR_W 0x4 /// Cache-inhibited partial write for Centaur putscom(). + +#define PBA_WRITE_TTYPE_DC PBA_WRITE_TTYPE_DMA_PR_WR // Don't care + + +// PBA write Tsize is only required for PBA_WRITE_TTYPE_LCO_M (where it +// actually specifies a core chiplet id) and PBA_WRITE_TTYPE_ATOMIC_RMW. + +#define PBA_WRITE_TSIZE_CHIPLET(chiplet) (chiplet) + +#define PBA_WRITE_TSIZE_ARMW_ADD 0x03 +#define PBA_WRITE_TSIZE_ARMW_AND 0x13 +#define PBA_WRITE_TSIZE_ARMW_OR 0x23 +#define PBA_WRITE_TSIZE_ARMW_XOR 0x33 + +#define PBA_WRITE_TSIZE_DC 0x0 + + +// PBA write gather timeouts are defined in terms of the number of 'pulses'. A +// pulse occurs every 64 OCI cycles. The timing of the last write of a +// sequence is variable, so the timeout will occur somewhere between (N - 1) * +// 64 and N * 64 OCI cycles. If write gather timeouts are disabled, the PBA +// holds the data until some condition occurs that causes it to disgorge the +// data. Slaves using cache-inhibited partial write never gather write +// data. Note from spec. : "Write gather timeouts must NOT be disabled if +// multiple masters are enabled to write through the PBA". The only case +// where write gather timeouts will be disabled is for the IPL-time injection +// of data into the L3 caches. Note that disabling write-gathering timeouts is +// different from disabling write-gathering altogether with the +// SLVCTL.dis_write_gather setting. + +#define PBA_WRITE_GATHER_TIMEOUT_DISABLE 0x0 +#define PBA_WRITE_GATHER_TIMEOUT_2_PULSES 0x4 +#define PBA_WRITE_GATHER_TIMEOUT_4_PULSES 0x5 +#define PBA_WRITE_GATHER_TIMEOUT_8_PULSES 0x6 +#define PBA_WRITE_GATHER_TIMEOUT_16_PULSES 0x7 + +/// PBA write gather timeout don't care assignment - see gpe_pba_parms_create() +#define PBA_WRITE_GATHER_TIMEOUT_DC -1 + + +// PBA read Ttype + +#define PBA_READ_TTYPE_CL_RD_NC 0x0 /// Cache line read +#define PBA_READ_TTYPE_CI_PR_RD 0x1 /// Cache-inhibited partial read for Centaur getscom(). + +/// PBA read TTYPE don't care assignment +#define PBA_READ_TTYPE_DC PBA_READ_TTYPE_CL_RD_NC + + +// PBA read prefetch options + +#define PBA_READ_PREFETCH_AUTO_EARLY 0x0 /// Aggressive prefetch +#define PBA_READ_PREFETCH_NONE 0x1 /// No prefetch +#define PBA_READ_PREFETCH_AUTO_LATE 0x2 /// Non-aggressive prefetch + +/// PBA read prefetch don't care assignment - see gpe_pba_parms_create() +#define PBA_READ_PREFETCH_DC -1 + + +// PBA PowerBus command scope and priority, and PBA defaults + +/// Nodal, Local Node +#define POWERBUS_COMMAND_SCOPE_NODAL 0x0 + +/// Group, Local 4-chip, (aka, node pump) +#define POWERBUS_COMMAND_SCOPE_GROUP 0x1 + +/// System, All units in the system +#define POWERBUS_COMMAND_SCOPE_SYSTEM 0x2 + +/// RGP, All units in the system (aka, system pump) +#define POWERBUS_COMMAND_SCOPE_RGP 0x3 + +/// Foreign, All units on the local chip, local SMP, and remote chip (pivot +/// nodes), In P8, only 100 and 101 are valid. +#define POWERBUS_COMMAND_SCOPE_FOREIGN0 0x4 + +/// Foreign, All units on the local chip, local SMP, and remote chip (pivot +/// nodes), In P8, only 100 and 101 are valid. +#define POWERBUS_COMMAND_SCOPE_FOREIGN1 0x5 + + +/// Default command scope for BCDE/BCUE transfers +#define PBA_POWERBUS_COMMAND_SCOPE_DEFAULT POWERBUS_COMMAND_SCOPE_NODAL + + + +// Abstract fields of the PBA Slave Reset register used in pba_slave_reset(), +// which checks 'n' for validity.p + +#define PBA_SLVRST_SET(n) (4 + (n)) +#define PBA_SLVRST_IN_PROG(n) (0x8 >> (n)) + +/// The default timeout for pba_slave_reset(). +/// +/// Currently the procedure pba_slave_reset() is thought to be an +/// initialization-only and/or lab-only procedure, so this long polling +/// timeout is not a problem. +#ifndef PBA_SLAVE_RESET_TIMEOUT +#define PBA_SLAVE_RESET_TIMEOUT SSX_MICROSECONDS(100) +#endif + + +// PBA Error/Panic codes + +#define PBA_SCOM_ERROR1 0x00722001 +#define PBA_SCOM_ERROR2 0x00722002 +#define PBA_SLVRST_TIMED_OUT1 0x00722003 +#define PBA_SLVRST_TIMED_OUT2 0x00722004 +#define PBA_INVALID_ARGUMENT_BARSET 0x00779005 +#define PBA_INVALID_ARGUMENT_RESET 0x00779006 +#define PBAX_INVALID_ARGUMENT_CONFIG 0x00779007 +#define PBAX_INVALID_ARGUMENT_TARGET 0x00779008 +#define PBAX_INVALID_OBJECT 0x00722009 + +#ifndef __ASSEMBLER__ + +/// The PBA extended address in the form of a 'firmware register' +/// +/// The extended address covers only bits 23:36 of the 50-bit PowerBus address. + +typedef union pba_extended_address { + + uint64_t value; + uint32_t word[2]; + struct { + uint64_t reserved0 : 23; + uint64_t extended_address : 14; + uint64_t reserved1 : 27; + } fields; +} pba_extended_address_t; + + +int +pba_barset_initialize(int idx, uint64_t base, int log_size); + +int +_pba_slave_reset(int id, SsxInterval timeout, SsxInterval sleep); + +int +pba_slave_reset(int id); + + +//////////////////////////////////////////////////////////////////////////// +// PBAX +//////////////////////////////////////////////////////////////////////////// + +// PBAX error/panic codes + +#define PBAX_SEND_TIMEOUT 0x00722901 +#define PBAX_SEND_ERROR 0x00722902 +#define PBAX_RECEIVE_ERROR 0x00722903 + +/// The number of receive queues implemented by PBAX +#define PBAX_QUEUES 2 + +/// The number of PBAX Node Ids +#define PBAX_NODES 8 + +/// The number of PBAX Chip Ids (and group Ids) +#define PBAX_CHIPS 8 +#define PBAX_GROUPS PBAX_CHIPS + +/// The maximum legal PBAX group mask +#define PBAX_GROUP_MASK_MAX 0xff + +// PBAX Send Message Scope + +#define PBAX_GROUP 1 +#define PBAX_SYSTEM 2 + +// PBAX Send Type + +#define PBAX_UNICAST 0 +#define PBAX_BROADCAST 1 + +// Default timeout for pbax_send() + +#ifndef PBAX_SEND_DEFAULT_TIMEOUT +#define PBAX_SEND_DEFAULT_TIMEOUT SSX_MICROSECONDS(30) +#endif + +/// An abstract target for PBAX send operations +/// +/// This structure contains an abstraction of a communication target for PBAX +/// send operations. An application using PBAX to transmit data first creates +/// an instance of the PbaxTarget for each abstract target using +/// pbax_target_create(), then calls pbax_send() or _pbax_send() with a +/// PbaxTarget and an 8-byte data packet to effect a transmission. +/// +/// For applications that use GPE programs to implement PBAX sends, a pointer +/// to this object could also be passed to the GPE program. + +typedef struct { + + /// The abstract target + /// + /// pbax_target_create() condenses the target parameters into a copy of + /// the PBAXSNDTX register used to configure the transmission. + pba_xsndtx_t target; + +} PbaxTarget; + + +int +pbax_target_create(PbaxTarget* target, + int type, int scope, int queue, + int node, int chip_or_group); + +int +pbax_configure(int master, int node, int chip, int group_mask); + +int +_pbax_send(PbaxTarget* target, uint64_t data, SsxInterval timeout); + +int +pbax_send(PbaxTarget* target, uint64_t data); + + +/// Enable the PBAX send mechanism + +static inline void +pbax_send_enable(void) +{ + pba_xcfg_t pxc; + + pxc.words.high_order = in32(PBA_XCFG); + pxc.fields.pbax_en = 1; + out32(PBA_XCFG, pxc.words.high_order); + +} + + +/// Disable the PBAX send mechanism + +static inline void +pbax_send_disable(void) +{ + pba_xcfg_t pxc; + + pxc.words.high_order = in32(PBA_XCFG); + pxc.fields.pbax_en = 0; + out32(PBA_XCFG, pxc.words.high_order); + +} + + +/// Clear the PBAX send error condition + +static inline void +pbax_clear_send_error(void) +{ + pba_xcfg_t pxc; + + pxc.words.high_order = in32(PBA_XCFG); + pxc.fields.snd_reset = 1; + out32(PBA_XCFG, pxc.words.high_order); +} + + +/// Clear the PBAX receive error condition + +static inline void +pbax_clear_receive_error(void) +{ + pba_xcfg_t pxc; + + pxc.words.high_order = in32(PBA_XCFG); + pxc.fields.rcv_reset = 1; + out32(PBA_XCFG, pxc.words.high_order); +} + +#endif /* __ASSEMBLER__ */ + +#endif /* __PGP_PBA_H__ */ diff --git a/src/ssx/pgp/pgp_pmc.c b/src/ssx/pgp/pgp_pmc.c new file mode 100755 index 0000000..bf3673b --- /dev/null +++ b/src/ssx/pgp/pgp_pmc.c @@ -0,0 +1,366 @@ +// $Id: pgp_pmc.c,v 1.2 2014/02/03 01:30:35 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_pmc.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_pmc.c +/// \brief PgP procedures and support for PMC operations +/// +/// <b> SCOM Operations </b> +/// +/// The PMC provides an indirect bridge from the OCI to the PIB/PCB. OCC +/// firmware therefore has the ability to do immediate putscom()/getscom() +/// operations in addition to the capabilities provided by the PORE-GPE +/// engines. In PgP, SCOM latency from OCC is expected to be in the range of +/// 150 - 1000 ns. The maximum latency of a PIB operation has a hard upper +/// bound derived from the hardware implementation. The putscom()/getscom() +/// drivers here take advantage of this upper bound and implement tight +/// timeouts, enforced by polling the timebase while waiting for the SCOM +/// operations to complete. +/// +/// The latencies are small enough and so well understood that the +/// getscom()/putscom() procedures operate in SSX_CRITICAL critical +/// sections. There should be no problem for thread-based procedures to be +/// written using getscom()/putscom() directly - in fact for short procedures +/// it may be less overhead to use getscom()/putscom() than queuing a PORE-GPE +/// program. All mainline procedures used by hard real-time code should +/// remain as PORE-GPE programs however. +/// +/// SCOM operations return non-zero error codes that may or may not indicate +/// an actual error, depending on which SCOM is being accessed. This error +/// code (or 0 for success) is returned as the value of getscom()/putscom(). +/// The error severity increases with the severity of the error: +/// \code +/// +/// #define PCB_ERROR_NONE 0 +/// #define PCB_ERROR_RESOURCE_OCCUPIED 1 +/// #define PCB_ERROR_CHIPLET_OFFLINE 2 +/// #define PCB_ERROR_PARTIAL_GOOD 3 +/// #define PCB_ERROR_ADDRESS_ERROR 4 +/// #define PCB_ERROR_CLOCK_ERROR 5 +/// #define PCB_ERROR_PACKET_ERROR 6 +/// #define PCB_ERROR_TIMEOUT 7 +/// \endcode +/// +/// The default configuration variable SCOM_ERROR_LIMIT defines the maximum +/// error code that will be returned - error codes above the limit (plus hard +/// timeouts and other protocol errors) cause an immediate kernel panic. In +/// the event of a non-0 error code, getscom() always sets the returned data +/// to 0. +/// +/// In addition to getscom()/putscom() that implement the above defined error +/// protocols, the raw APIs _getscom()/_putscom() are also available and +/// allow the application full control over timeouts and error handling on a +/// SCOM-by-SCOM basis. +/// +/// \bug Modify getscom/putscom to return the SSX error codes rather than +/// 1-7. +/// +/// \bug Implement and use a generic poll_with_timeout(f, arg, t) + +#include "ssx.h" +#include "pgp_pmc.h" + + +//////////////////////////////////////////////////////////////////////////// +// SCOM +//////////////////////////////////////////////////////////////////////////// + +// Common SCOM polling loop with software timeout. The PMC is always polled +// at least twice to guarantee that we always poll once after a timeout. + +static int +poll_scom(SsxInterval timeout, pmc_o2p_ctrl_status_reg_t *cs) +{ + SsxTimebase start; + int timed_out; + + start = ssx_timebase_get(); + timed_out = 0; + do { + cs->value = in32(PMC_O2P_CTRL_STATUS_REG); + if (!(cs->fields.o2p_ongoing)) { + break; + } + if (timed_out) { + return -SCOM_TIMEOUT_ERROR; + } + timed_out = + ((timeout != SSX_WAIT_FOREVER) && + ((ssx_timebase_get() - start) > timeout)); + } while (1); + + return 0; +} + + +/// A raw getscom() through the PMC OCI/PIB bridge +/// +/// \param address A standard 32-bit SCOM address, including multicast +/// addresses. +/// +/// \param data Points to a container for the returned data. +/// +/// \param timeout The software timeout as an SSX interval (timebase ticks), +/// or the special value SSX_WAIT_FOREVER to indicate no software timeout. +/// +/// This routine executes in an SSX_CRITICAL critical section. +/// +/// Unlike most other APIs, this API returns both positive and negative error +/// codes, as well as the 0 code for success. In the event of PCB errors, the +/// returned \a data is obtained from the PMC O2P data registers. In the +/// event of non-PCB errors, the caller \a data is not modified. +/// +/// If the transaction experiences a software timeout (controlled by the \a +/// timeout parameter) or a protocol error, the PMC PIB master will be left in +/// a state in which it is illegal to perform further SCOM access through the +/// PMC until the ongoing transaction is finished. +/// +/// \retval 0 Success +/// +///\ retval 1-7 A PCB error code. See \c pcb_common.h +/// +/// \retval -SCOM_TIMEOUT_ERROR The software timeout specified by the \a +/// timeout parameter expired before the transaction completed. +/// +/// retval -SCOM_PROTOCOL_ERROR_GETSCOM_BUSY The PMC SCOM engine was busy when +/// the call was made. + +int +_getscom(uint32_t address, uint64_t *data, SsxInterval timeout) +{ + pmc_o2p_addr_reg_t addr; + pmc_o2p_ctrl_status_reg_t cs; + SsxMachineContext ctx; + Uint64 data64; + int rc; + + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + + // Check for a transaction already ongoing + + cs.value = in32(PMC_O2P_CTRL_STATUS_REG); + if (cs.fields.o2p_ongoing) { + ssx_critical_section_exit(&ctx); + return -SCOM_PROTOCOL_ERROR_GETSCOM_BUSY; + } + + // Start the read. The 'read' bit is forced into the address. Writing + // the PMC_O2P_ADDR_REG starts the read. + + addr.value = address; + addr.fields.o2p_read_not_write = 1; + out32(PMC_O2P_ADDR_REG, addr.value); + + // Polling and return. + + rc = poll_scom(timeout, &cs); + + data64.word[0] = in32(PMC_O2P_RECV_DATA_HI_REG); + data64.word[1] = in32(PMC_O2P_RECV_DATA_LO_REG); + *data = data64.value; + + ssx_critical_section_exit(&ctx); + + if (rc) { + return rc; + } else { + return cs.fields.o2p_scresp; + } +} + + +/// getscom() through the PMC OCI/PIB bridge +/// +/// \param address A standard 32-bit SCOM address, including multicast +/// addresses. +/// +/// \param data Points to a container for the returned data. +/// +/// This routine executes in an SSX_CRITICAL critical section. +/// +/// Unlike most other APIs, this API returns positive error +/// codes, as well as the 0 code for success. In the event of PCB errors, the +/// returned \a data is set to 0. +/// +/// If the transaction experiences a software timeout (controlled by the \a +/// timeout parameter), a protocol error, or a PCB error greater than the +/// configuration constant SCOM_ERROR_LIMIT this routine causes a kernel +/// panic. This may leave the PMC PIB master in a state in which it is illegal +/// to perform further SCOM access through the PMC (until the ongoing +/// transaction is finished.) +/// +/// \retval 0 Success +/// +///\ retval 1-7 A PCB error code. See \c pcb_common.h + +int +getscom(uint32_t address, uint64_t *data) +{ + int rc; + + rc = _getscom(address, data, SCOM_TIMEOUT); + if (rc == 0) { + return 0; + } + + if ((rc > 0) && (rc <= SCOM_ERROR_LIMIT)) { + *data = 0; + } else { + + printk("getscom(0x%08x, %p) : Failed with error %d\n", + address, data, rc); + + if (rc > 0) { + switch (rc) { + case 1: SSX_PANIC(SCOM_PCB_ERROR_1_GETSCOM); break; + case 2: SSX_PANIC(SCOM_PCB_ERROR_2_GETSCOM); break; + case 3: SSX_PANIC(SCOM_PCB_ERROR_3_GETSCOM); break; + case 4: SSX_PANIC(SCOM_PCB_ERROR_4_GETSCOM); break; + case 5: SSX_PANIC(SCOM_PCB_ERROR_5_GETSCOM); break; + case 6: SSX_PANIC(SCOM_PCB_ERROR_6_GETSCOM); break; + default: SSX_PANIC(SCOM_PCB_ERROR_7_GETSCOM); break; + } + } else if (rc == -SCOM_TIMEOUT_ERROR) { + SSX_PANIC(SCOM_TIMEOUT_ERROR_GETSCOM); + } else { + SSX_PANIC(SCOM_PROTOCOL_ERROR_GETSCOM); + } + } + + return rc; +} + + +/// A raw putscom() through the PMC OCI/PIB bridge +/// +/// \param address A standard 32-bit SCOM address, including multicast +/// addresses. +/// +/// \param data The SCOM write data +/// +/// \param timeout The software timeout as an SSX interval (timebase ticks), +/// or the special value SSX_WAIT_FOREVER to indicate no timeout. +/// +/// This routine executes in an SSX_CRITICAL critical section. +/// +/// Unlike most other APIs, this API returns both positive and negative error +/// codes, as well as the 0 code for success. +/// +/// If the transaction experiences a software timeout (controlled by the \a +/// timeout parameter) or a protocol error, the PMC PIB master will be left in +/// a state in which it is illegal to perform further SCOM access through the +/// PMC until the ongoing transaction is finished. +/// +/// \retval 0 Success +/// +/// \retval 1-7 A PCB error code. See \c pcb_common.h +/// +/// \retval -SCOM_TIMEOUT The software timeout specified by the \a timeout +/// parameter expired before the transaction completed. +/// +/// \retval -SCOM_PROTOCOL_ERROR_PUTSCOM_BUSY The PMC SCOM engine was busy when +/// the call was made. + +int +_putscom(uint32_t address, uint64_t data, SsxInterval timeout) +{ + pmc_o2p_addr_reg_t addr; + pmc_o2p_ctrl_status_reg_t cs; + SsxMachineContext ctx; + Uint64 data64; + int rc; + + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + + // Check for a transaction already ongoing + + cs.value = in32(PMC_O2P_CTRL_STATUS_REG); + if (cs.fields.o2p_ongoing) { + ssx_critical_section_exit(&ctx); + return -SCOM_PROTOCOL_ERROR_PUTSCOM_BUSY; + } + + // Start the write. The 'write' bit is cleared in the address. Here the + // PIB write starts when the PMC_O2P_SEND_DATA_LO_REG is written. + + addr.value = address; + addr.fields.o2p_read_not_write = 0; + out32(PMC_O2P_ADDR_REG, addr.value); + + data64.value = data; + out32(PMC_O2P_SEND_DATA_HI_REG, data64.word[0]); + out32(PMC_O2P_SEND_DATA_LO_REG, data64.word[1]); + + // Poll and return. + + rc = poll_scom(timeout, &cs); + + ssx_critical_section_exit(&ctx); + + if (rc) { + return rc; + } else { + return cs.fields.o2p_scresp; + } +} + + +/// putscom() through the PMC OCI/PIB bridge +/// +/// \param address A standard 32-bit SCOM address, including multicast +/// addresses. +/// +/// \param data The SCOM write data. +/// +/// This routine executes in an SSX_CRITICAL critical section. +/// +/// Unlike most other APIs, this API returns positive error +/// codes, as well as the 0 code for success. +/// +/// If the transaction experiences a software timeout (controlled by the \a +/// timeout parameter), a protocol error, or a PCB error greater than the +/// configuration constant SCOM_ERROR_LIMIT this routine causes a kernel +/// panic. This may leave the PMC PIB master in a state in which it is illegal +/// to perform further SCOM access through the PMC (until the ongoing +/// transaction is finished.) +/// +/// \retval 0 Success +/// +/// \retval 1-7 A PCB error code. See \c pcb_common.h + +int +putscom(uint32_t address, uint64_t data) +{ + int rc; + + rc = _putscom(address, data, SCOM_TIMEOUT); + + if ((rc == 0) || ((rc > 0) && (rc <= SCOM_ERROR_LIMIT))) { + return rc; + } + + printk("putscom(0x%08x, 0x%016llx) : Failed with error %d\n", + address, data, rc); + + if (rc > 0) { + switch (rc) { + case 1: SSX_PANIC(SCOM_PCB_ERROR_1_PUTSCOM); break; + case 2: SSX_PANIC(SCOM_PCB_ERROR_2_PUTSCOM); break; + case 3: SSX_PANIC(SCOM_PCB_ERROR_3_PUTSCOM); break; + case 4: SSX_PANIC(SCOM_PCB_ERROR_4_PUTSCOM); break; + case 5: SSX_PANIC(SCOM_PCB_ERROR_5_PUTSCOM); break; + case 6: SSX_PANIC(SCOM_PCB_ERROR_6_PUTSCOM); break; + default: SSX_PANIC(SCOM_PCB_ERROR_7_PUTSCOM); break; + } + } else if (rc == -SCOM_TIMEOUT_ERROR) { + SSX_PANIC(SCOM_TIMEOUT_ERROR_PUTSCOM); + } else { + SSX_PANIC(SCOM_PROTOCOL_ERROR_PUTSCOM); + } + + return rc; +} diff --git a/src/ssx/pgp/pgp_pmc.h b/src/ssx/pgp/pgp_pmc.h new file mode 100755 index 0000000..1b372db --- /dev/null +++ b/src/ssx/pgp/pgp_pmc.h @@ -0,0 +1,105 @@ +#ifndef __PGP_PMC_H__ +#define __PGP_PMC_H__ + +// $Id: pgp_pmc.h,v 1.2 2014/02/03 01:30:35 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_pmc.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_pmc.h +/// \brief PgP procedures and support for PMC operations + +#include "ssx.h" + +#include "pgp_common.h" +#include "pmc_register_addresses.h" +#include "pmc_firmware_registers.h" + +//////////////////////////////////////////////////////////////////////////// +// SCOM +//////////////////////////////////////////////////////////////////////////// + +#ifndef __ASSEMBLER__ + +int +_getscom(uint32_t address, uint64_t *data, SsxInterval timeout); + +int +getscom(uint32_t address, uint64_t *data); + +int +_putscom(uint32_t address, uint64_t data, SsxInterval timeout); + +int +putscom(uint32_t address, uint64_t data); + +#endif /* __ASSEMBLER__ */ + +// Error/Panic Codes + +#define SCOM_PCB_ERROR_1_GETSCOM 0x00726601 +#define SCOM_PCB_ERROR_2_GETSCOM 0x00726602 +#define SCOM_PCB_ERROR_3_GETSCOM 0x00726603 +#define SCOM_PCB_ERROR_4_GETSCOM 0x00726604 +#define SCOM_PCB_ERROR_5_GETSCOM 0x00726605 +#define SCOM_PCB_ERROR_6_GETSCOM 0x00726606 +#define SCOM_PCB_ERROR_7_GETSCOM 0x00726607 +#define SCOM_PCB_ERROR_1_PUTSCOM 0x00726608 +#define SCOM_PCB_ERROR_2_PUTSCOM 0x00726609 +#define SCOM_PCB_ERROR_3_PUTSCOM 0x0072660a +#define SCOM_PCB_ERROR_4_PUTSCOM 0x0072660b +#define SCOM_PCB_ERROR_5_PUTSCOM 0x0072660c +#define SCOM_PCB_ERROR_6_PUTSCOM 0x0072660d +#define SCOM_PCB_ERROR_7_PUTSCOM 0x0072660e + +#define SCOM_TIMEOUT_ERROR 0x00726610 +#define SCOM_TIMEOUT_ERROR_GETSCOM 0x00726611 +#define SCOM_TIMEOUT_ERROR_PUTSCOM 0x00726612 +#define SCOM_PROTOCOL_ERROR_GETSCOM 0x00726613 +#define SCOM_PROTOCOL_ERROR_PUTSCOM 0x00726614 +#define SCOM_PROTOCOL_ERROR_GETSCOM_BUSY 0x00726615 +#define SCOM_PROTOCOL_ERROR_PUTSCOM_BUSY 0x00726616 + + +/// The default timeout for getscom()/putscom() +/// +/// This timeout is enforced by the firmware to guarantee a timeout regardless +/// of the hardware setup. +/// +/// The expectation is that the PgP hardware will be set up to enforce a PCB +/// timeout of 8K cycles, or 16.384us @ 500 MHz. A timeout only occurs if +/// someone erroneously issues a SCOM for a chiplet that does not exist. If +/// this happens, then all other SCOMS waiting for the timed-out SCOM to +/// finish will have to wait as well. Aside from the timeout error, the +/// hardware arbitration and hard latency calculations guarantee that a SCOM +/// from any master will complete in under 1us, regardless of PCB utilization. +/// +/// Assuming that the PCB timeout is a rare event that will only happen when a +/// console user types an illegal address for getscom/putscom, then we should +/// be able to use 17us as a hard upper bound for a soft timeout. In practice +/// this software timeout should never be observed - if it is, then something +/// (either the setup, hardware or firmware) must be broken. + +#ifndef SCOM_TIMEOUT +#define SCOM_TIMEOUT SSX_MICROSECONDS(17) +#endif + + +/// The default getscom()/putscom() error limit. +/// +/// This defines the maximum PCB error return code which will not cause +/// getscom()/putscom() to panic. The choice of this error limit is +/// application dependent. For lab applications we should never try to SCOM a +/// partial-good chiplet, so the limit is set at PCB_ERROR_CHIPLET_OFFLINE. +/// For production applications it may be that notification of garded cores is +/// late, so production code may need to handle PCB_ERROR_PARTIAL_GOOD as +/// well. + +#ifndef SCOM_ERROR_LIMIT +#define SCOM_ERROR_LIMIT PCB_ERROR_CHIPLET_OFFLINE +#endif + +#endif // __PGP_PMC_H__ diff --git a/src/ssx/pgp/pgp_pore.h b/src/ssx/pgp/pgp_pore.h new file mode 100755 index 0000000..e40ccac --- /dev/null +++ b/src/ssx/pgp/pgp_pore.h @@ -0,0 +1,39 @@ +#ifndef __PGP_PORE_H__ +#define __PGP_PORE_H__ + +// $Id: pgp_pore.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_pore.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_pore.h +/// \brief PORE unit header. Local and mechanically generated macros. + +#include "pore_register_addresses.h" +#include "pore_firmware_registers.h" + +/// The parameter for GPE-protocol triggering is the low-order word of the +/// EXE_TRIGGER register +#define PORE_EXE_PARAMETER_OFFSET (PORE_EXE_TRIGGER_OFFSET + 4) + +/// The PORE OCI address space descriptor +#define PORE_ADDRESS_SPACE_OCI 0x8000 + +/// The PORE BRAI opcode +#define PORE_BRAI 0xa2000000 + +/// The PORE BRAD D0 opcode +#define PORE_BRAD_D0 0x38500000 + + +#ifndef __ASSEMBLER__ + +/// The putative type of PORE program entry points - to make GCC happy +typedef void *(PoreEntryPoint)(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* __PGP_PORE_H__ */ diff --git a/src/ssx/pgp/pgp_sramctl.h b/src/ssx/pgp/pgp_sramctl.h new file mode 100755 index 0000000..fe2ed69 --- /dev/null +++ b/src/ssx/pgp/pgp_sramctl.h @@ -0,0 +1,18 @@ +#ifndef __PGP_SRAMCTL_H__ +#define __PGP_SRAMCTL_H__ + +// $Id: pgp_sramctl.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_sramctl.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_sramctl.h +/// \brief SRAMCTL unit header. Local and mechanically generated macros. + +#include "sramctl_register_addresses.h" +#include "sramctl_firmware_registers.h" + +#endif /* __PGP_SRAMCTL_H__ */ diff --git a/src/ssx/pgp/pgp_trace.h b/src/ssx/pgp/pgp_trace.h new file mode 100755 index 0000000..3544ce0 --- /dev/null +++ b/src/ssx/pgp/pgp_trace.h @@ -0,0 +1,155 @@ +#ifndef __PGP_TRACE_H__ +#define __PGP_TRACE_H__ + +// $Id: pgp_trace.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_trace.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_trace.h +/// \brief Implementation of SSX_TRACE macros for PgP +/// +/// Kernel and application tracing uses the PBA "OCI Marker Space", a 64KB OCI +/// register space implemented by PBA. When enabled in the PBA, any OCI write +/// transactions of any size are ACK'ed by the PBA and the data is ignored. +/// This creates an OCI transaction record that can be captured by the NHTM +/// for later analysis. +/// +/// SSX provides a generic SSX_TRACE() macro that accepts a single +/// parameter. On PgP, valid parameters are integers in the range +/// 0x0,...,0xffff. The PgP SSX kernel reserves trace addresses +/// 0xe000,...,0xffff for kernel event traces. Applications are free to use +/// the other trace addresses in the range 0x0000,...,0xdfff as they see fit. +/// +/// Application tracing is globally disabled by default, and is enabled by +/// defining the switch SSX_TRACE_ENABLE=1. Kernel event tracing is also +/// globally disabled by default, and is enabled by defining the switch +/// SSX_KERNEL_TRACE_ENABLE=1. Kernel event tracing adds overhead to every +/// interrupt handler and kernel API so should probably remain disabled unless +/// required. +/// +/// The Simics PBA model supports trace reporting, either to stdout or to a +/// file. To enable trace reporting set pba->trace_report = 1. To capture +/// traces to a file other than stdout, set pba->trace_file = \<filename\>. The +/// Simics model understands SSX kernel trace events and produces a readable +/// commentary of kernel traces events - user events will be reported simply +/// as the integer tag. + +#include "pgp_common.h" + +/// Output an OCI Trace Marker +/// +/// See the comments for the file pgp_trace.h + +#if SSX_TRACE_ENABLE +#define SSX_TRACE(event) out8(PBA_OCI_MARKER_BASE + (event), 0) +#endif + +#if SSX_KERNEL_TRACE_ENABLE + +// Note: The *BASE constants are defined in pgp_common.h + +#define SSX_KERNEL_TRACE(event) out8(PBA_OCI_MARKER_BASE + (event), 0) + +#define SSX_TRACE_THREAD_SLEEP(priority) \ + SSX_KERNEL_TRACE(SSX_TRACE_THREAD_SLEEP_BASE + priority) + +#define SSX_TRACE_THREAD_WAKEUP(priority) \ + SSX_KERNEL_TRACE(SSX_TRACE_THREAD_WAKEUP_BASE + priority) + +#define SSX_TRACE_THREAD_SEMAPHORE_PEND(priority) \ + SSX_KERNEL_TRACE(SSX_TRACE_THREAD_SEMAPHORE_PEND_BASE + priority) + +#define SSX_TRACE_THREAD_SEMAPHORE_POST(priority) \ + SSX_KERNEL_TRACE(SSX_TRACE_THREAD_SEMAPHORE_POST_BASE + priority) + +#define SSX_TRACE_THREAD_SEMAPHORE_TIMEOUT(priority) \ + SSX_KERNEL_TRACE(SSX_TRACE_THREAD_SEMAPHORE_TIMEOUT_BASE + priority) + +#define SSX_TRACE_THREAD_SUSPENDED(priority) \ + SSX_KERNEL_TRACE(SSX_TRACE_THREAD_SUSPENDED_BASE + priority) + +#define SSX_TRACE_THREAD_DELETED(priority) \ + SSX_KERNEL_TRACE(SSX_TRACE_THREAD_DELETED_BASE + priority) + +#define SSX_TRACE_THREAD_COMPLETED(priority) \ + SSX_KERNEL_TRACE(SSX_TRACE_THREAD_COMPLETED_BASE + priority) + +#define SSX_TRACE_THREAD_MAPPED_RUNNABLE(priority) \ + SSX_KERNEL_TRACE(SSX_TRACE_THREAD_MAPPED_RUNNABLE_BASE + priority) + +#define SSX_TRACE_THREAD_MAPPED_SEMAPHORE_PEND(priority) \ + SSX_KERNEL_TRACE(SSX_TRACE_THREAD_MAPPED_SEMAPHORE_PEND_BASE + priority) + +#define SSX_TRACE_THREAD_MAPPED_SLEEPING(priority) \ + SSX_KERNEL_TRACE(SSX_TRACE_THREAD_MAPPED_SLEEPING_BASE + priority) + +#endif /* SSX_KERNEL_TRACE_ENABLE */ + + +#ifdef __ASSEMBLER__ + +// NB: CPP macros are not expanded as arguments to .if in GAS macro +// definitions. That's why e.g. we have to use _liw instead of _liwa. + +#if SSX_KERNEL_TRACE_ENABLE + + .macro SSX_TRACE_CRITICAL_IRQ_ENTRY, irqreg, scratch + _liw \scratch, (PBA_OCI_MARKER_BASE + SSX_TRACE_CRITICAL_IRQ_ENTRY_BASE) + stbx \irqreg, \irqreg, \scratch + eieio + .endm + + .macro SSX_TRACE_CRITICAL_IRQ_EXIT, scratch0, scratch1 + _liw \scratch0, (PBA_OCI_MARKER_BASE + SSX_TRACE_CRITICAL_IRQ_EXIT_BASE) + mfusprg0 \scratch1 + extrwi \scratch1, \scratch1, 8, 16 + stbx \scratch1, \scratch0, \scratch1 + eieio + .endm + + .macro SSX_TRACE_NONCRITICAL_IRQ_ENTRY, irqreg, scratch + _liw \scratch, (PBA_OCI_MARKER_BASE + SSX_TRACE_NONCRITICAL_IRQ_ENTRY_BASE) + stbx \irqreg, \irqreg, \scratch + eieio + .endm + + .macro SSX_TRACE_NONCRITICAL_IRQ_EXIT, scratch0, scratch1 + _liw \scratch0, (PBA_OCI_MARKER_BASE + SSX_TRACE_NONCRITICAL_IRQ_EXIT_BASE) + mfusprg0 \scratch1 + extrwi \scratch1, \scratch1, 8, 16 + stbx \scratch1, \scratch0, \scratch1 + eieio + .endm + + .macro SSX_TRACE_THREAD_SWITCH, priority, scratch + _liw \scratch, (PBA_OCI_MARKER_BASE + SSX_TRACE_THREAD_SWITCH_BASE) + stbx \priority, \priority, \scratch + eieio + .endm + +#else /* SSX_KERNEL_TRACE_ENABLE */ + + .macro SSX_TRACE_CRITICAL_IRQ_ENTRY, irq, scratch + .endm + + .macro SSX_TRACE_CRITICAL_IRQ_EXIT, scratch0, scratch1 + .endm + + .macro SSX_TRACE_NONCRITICAL_IRQ_ENTRY, irq, scratch + .endm + + .macro SSX_TRACE_NONCRITICAL_IRQ_EXIT, scratch0, scratch1 + .endm + + .macro SSX_TRACE_THREAD_SWITCH, priority, scratch + .endm + +#endif /* SSX_KERNEL_TRACE_ENABLE */ + +#endif /* __ASSEMBLER__ */ + +#endif /* __PGP_TRACE_H__ */ diff --git a/src/ssx/pgp/pgp_vrm.h b/src/ssx/pgp/pgp_vrm.h new file mode 100755 index 0000000..aaa6760 --- /dev/null +++ b/src/ssx/pgp/pgp_vrm.h @@ -0,0 +1,223 @@ +#ifndef __PGP_VRM_H__ +#define __PGP_VRM_H__ + +// $Id: pgp_vrm.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/pgp_vrm.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pgp_vrm.h +/// \brief Header for PgP VRM device drivers. Some constants are also held in +/// pgp_common.h. + +#include "pgp_common.h" + + +#ifndef __ASSEMBLER__ + +/// VRM Command Header +/// +/// This structure defines the values written on the SPI interface for +/// 'read' commands. + +//typedef union { +// uint64_t value; +// uint32_t word[2]; +// struct { +// uint64_t address : 4; +// uint64_t command : 4; +// } fields; +//} vrm_command_t; + + +/// VRM Write Transaction Command +/// +/// The 8-bit \a phase_enable is an 8-bit VRM-11 VID code +/// +/// The 8-bit \a vcs_offset is an 8-bit signed offset + +typedef union { + uint64_t value; + uint32_t word[2]; + struct { + uint64_t command : 4; + uint64_t phase_enable : 4; + uint64_t vdd_vid : 8; + uint64_t vcs_offset : 8; + uint64_t master_crc : 8; + } fields; +} vrm_write_transaction_t; + + +/// VRM Write Transaction Response +/// writes status is duplicated 3x for the minority detect feature. + +typedef union { + uint64_t value; + uint32_t word[2]; + struct { + uint64_t write_status0 : 8; + uint64_t write_status1 : 8; + uint64_t write_status2 : 8; + uint64_t optional_crc : 8; + } fields; +} vrm_write_resp_t; + + + +/// VRM Read State Command +/// reserved field should be sent as 0s + +typedef union { + uint64_t value; + uint32_t word[2]; + struct { + uint64_t command : 4; + uint64_t reserved : 20; + uint64_t master_crc : 8; + } fields; +} vrm_read_state_t; + + +/// VRM Read State Response +/// Results are duplicated 3x for the minority detecte feature. + +typedef union { + uint64_t value; + uint32_t word[2]; + struct { + uint64_t read_ready0 : 1; + uint64_t minus_nplus1_0 : 1; + uint64_t minus_n0 : 1; + uint64_t reserved1_0 : 1; + uint64_t vrm_fan0 : 1; + uint64_t vrm_overtemp0 : 1; + uint64_t reserved2_0 : 2; + uint64_t read_ready1 : 1; + uint64_t minus_nplus1_1 : 1; + uint64_t minus_n1 : 1; + uint64_t reserved1_1 : 1; + uint64_t vrm_fan1 : 1; + uint64_t vrm_overtemp1 : 1; + uint64_t reserved2_1 : 2; + uint64_t read_ready2 : 1; + uint64_t minus_nplus1_2 : 1; + uint64_t minus_n2 : 1; + uint64_t reserved1_2 : 1; + uint64_t vrm_fan2 : 1; + uint64_t vrm_overtemp2 : 1; + uint64_t reserved2_2 : 2; + uint64_t slave_crc : 8; + } fields; +} vrm_read_state_resp_t; + +/// VRM Read Voltage Command +/// reserved field should be sent as 0s + +typedef union { + uint64_t value; + uint32_t word[2]; + struct { + uint64_t command : 4; + uint64_t rail : 4; + uint64_t reserved : 1; + uint64_t master_crc : 8; + } fields; +} vrm_read_voltage_t; + + +/// VRM Read Voltage Response +/// Results are duplicated 3x for the minority detect feature. + +typedef union { + uint64_t value; + uint32_t word[2]; + struct { + uint64_t vid0 : 8; + uint64_t vid1 : 8; + uint64_t vid2 : 8; + uint64_t slave_crc : 8; + } fields; +} vrm_read_voltage_resp_t; + + +/// VRM Read Current 1 Response +/// +/// The 16-bit current readings come from 12-bit DACS; the DAC output is +/// right-padded with 0b0000. The current units are 0.025 Ampere. + +//typedef union { +// uint64_t value; +// uint32_t word[2]; +// struct { +// uint64_t header : 8; +// uint64_t read_not_ready : 1; +// uint64_t minus_nplus1 : 1; +// uint64_t minus_n : 1; +// uint64_t reserved0 : 1; +// uint64_t vrm_fan : 1; +// uint64_t vrm_overtemp : 1; +// uint64_t reserved1 : 2; +// uint64_t vdd_current : 16; +// uint64_t vcs_current : 16; +// uint64_t vio_current : 16; +// } fields; +//} vrm_read_current_1_t; + + +/// VRM Read Current 2 Response +/// +/// The 16-bit current readings come from 12-bit DACS; the DAC output is +/// right-padded with 0b0000. The current units are 0.025 Ampere. + +//typedef union { +// uint64_t value; +// uint32_t word[2]; +// struct { +// uint64_t header : 8; +// uint64_t read_not_ready : 1; +// uint64_t minus_nplus1 : 1; +// uint64_t minus_n : 1; +// uint64_t reserved0 : 1; +// uint64_t vrm_fan : 1; +// uint64_t vrm_overtemp : 1; +// uint64_t reserved1 : 2; +// uint64_t spare1_current : 16; +// uint64_t spare2_current : 16; +// uint64_t spare3_current : 16; +// } fields; +//} vrm_read_current_2_t; + +#endif /* __ASSEMBLER__ */ + +// These are the default values for the SPIVRM/O2S interface + +#define SPIVRM_BITS 71 /* Actual # of bits minus 1 */ +#define SPIVRM_CPOL 0 /* Clock polarity */ +#define SPIVRM_CPHA 0 /* Clock phase */ +#define SPIVRM_FREQUENCY_HZ 16000000 /* 16 MHz */ +#define SPIVRM_ENABLE_ECC 1 +#define SPIVRM_NPORTS 3 /* Maximum # of ports supported by HW */ +#define SPIVRM_NRAILS 2 /* Maximum # of rails supported by read voltage cmd*/ +#define SPIVRM_ENABLED_PORTS 0x4 /* 3 bit mask, left justified */ +#define SPIVRM_PHASES 15 /* System dependent */ + +/// Convert an integer index into a VRM designator (mask) +#define SPIVRM_PORT(i) (1 << (SPIVRM_NPORTS - (i) - 1)) + +// SPIVRM specific setup defaults + +#define SPIVRM_READ_STATUS_DELAY 48 /* Cycles, system dependent */ +#define SPIVRM_ADDRESS 0 /* First 4 bits of SPIVRM packet */ + +// Default values for the O2S bridge + +#define O2S_BRIDGE_ENABLE 1 +#define O2S_READ_DELAY 48 /* Cycles, system dependent */ +#define O2S_ADDRESS 0 /* First 4 bits of O2S packet */ + + +#endif /* __PGP_VRM_H__ */ diff --git a/src/ssx/pgp/registers/centaur_firmware_registers.h b/src/ssx/pgp/registers/centaur_firmware_registers.h new file mode 100755 index 0000000..39f168f --- /dev/null +++ b/src/ssx/pgp/registers/centaur_firmware_registers.h @@ -0,0 +1,1496 @@ +#ifndef __CENTAUR_FIRMWARE_REGISTERS_H__ +#define __CENTAUR_FIRMWARE_REGISTERS_H__ + +// $Id: centaur_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/centaur_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file centaur_firmware_registers.h +/// \brief C register structs for the CENTAUR unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union centaur_device_id { + + 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 cfam_id : 32; + uint64_t module_id : 2; + uint64_t _reserved0 : 30; +#else + uint64_t _reserved0 : 30; + uint64_t module_id : 2; + uint64_t cfam_id : 32; +#endif // _BIG_ENDIAN + } fields; +} centaur_device_id_t; + + + +typedef union centaur_mbs_fir_reg { + + 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 host_protocol_error : 1; + uint64_t int_protocol_error : 1; + uint64_t invalid_address_error : 1; + uint64_t external_timeout : 1; + uint64_t internal_timeout : 1; + uint64_t int_buffer_ce : 1; + uint64_t int_buffer_ue : 1; + uint64_t int_buffer_sue : 1; + uint64_t int_parity_error : 1; + uint64_t cache_srw_ce : 1; + uint64_t cache_srw_ue : 1; + uint64_t cache_srw_sue : 1; + uint64_t cache_co_ce : 1; + uint64_t cache_co_ue : 1; + uint64_t cache_co_sue : 1; + uint64_t dir_ce : 1; + uint64_t dir_ue : 1; + uint64_t dir_member_deleted : 1; + uint64_t dir_all_members_deleted : 1; + uint64_t lru_error : 1; + uint64_t edram_error : 1; + uint64_t emergency_throttle_set : 1; + uint64_t host_inband_read_error : 1; + uint64_t host_inband_write_error : 1; + uint64_t occ_inband_read_error : 1; + uint64_t occ_inband_write_error : 1; + uint64_t srb_buffer_ce : 1; + uint64_t srb_buffer_ue : 1; + uint64_t srb_buffer_sue : 1; + uint64_t dir_purge_ce : 1; + uint64_t spare_fir30 : 1; + uint64_t spare_fir31 : 1; + uint64_t internal_scom_error : 1; + uint64_t internal_scom_error_copy : 1; + uint64_t _reserved0 : 30; +#else + uint64_t _reserved0 : 30; + uint64_t internal_scom_error_copy : 1; + uint64_t internal_scom_error : 1; + uint64_t spare_fir31 : 1; + uint64_t spare_fir30 : 1; + uint64_t dir_purge_ce : 1; + uint64_t srb_buffer_sue : 1; + uint64_t srb_buffer_ue : 1; + uint64_t srb_buffer_ce : 1; + uint64_t occ_inband_write_error : 1; + uint64_t occ_inband_read_error : 1; + uint64_t host_inband_write_error : 1; + uint64_t host_inband_read_error : 1; + uint64_t emergency_throttle_set : 1; + uint64_t edram_error : 1; + uint64_t lru_error : 1; + uint64_t dir_all_members_deleted : 1; + uint64_t dir_member_deleted : 1; + uint64_t dir_ue : 1; + uint64_t dir_ce : 1; + uint64_t cache_co_sue : 1; + uint64_t cache_co_ue : 1; + uint64_t cache_co_ce : 1; + uint64_t cache_srw_sue : 1; + uint64_t cache_srw_ue : 1; + uint64_t cache_srw_ce : 1; + uint64_t int_parity_error : 1; + uint64_t int_buffer_sue : 1; + uint64_t int_buffer_ue : 1; + uint64_t int_buffer_ce : 1; + uint64_t internal_timeout : 1; + uint64_t external_timeout : 1; + uint64_t invalid_address_error : 1; + uint64_t int_protocol_error : 1; + uint64_t host_protocol_error : 1; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbs_fir_reg_t; + + + +typedef union centaur_mbs_fir_reg_and { + + 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 host_protocol_error : 1; + uint64_t int_protocol_error : 1; + uint64_t invalid_address_error : 1; + uint64_t external_timeout : 1; + uint64_t internal_timeout : 1; + uint64_t int_buffer_ce : 1; + uint64_t int_buffer_ue : 1; + uint64_t int_buffer_sue : 1; + uint64_t int_parity_error : 1; + uint64_t cache_srw_ce : 1; + uint64_t cache_srw_ue : 1; + uint64_t cache_srw_sue : 1; + uint64_t cache_co_ce : 1; + uint64_t cache_co_ue : 1; + uint64_t cache_co_sue : 1; + uint64_t dir_ce : 1; + uint64_t dir_ue : 1; + uint64_t dir_member_deleted : 1; + uint64_t dir_all_members_deleted : 1; + uint64_t lru_error : 1; + uint64_t edram_error : 1; + uint64_t emergency_throttle_set : 1; + uint64_t host_inband_read_error : 1; + uint64_t host_inband_write_error : 1; + uint64_t occ_inband_read_error : 1; + uint64_t occ_inband_write_error : 1; + uint64_t srb_buffer_ce : 1; + uint64_t srb_buffer_ue : 1; + uint64_t srb_buffer_sue : 1; + uint64_t dir_purge_ce : 1; + uint64_t spare_fir30 : 1; + uint64_t spare_fir31 : 1; + uint64_t internal_scom_error : 1; + uint64_t internal_scom_error_copy : 1; + uint64_t _reserved0 : 30; +#else + uint64_t _reserved0 : 30; + uint64_t internal_scom_error_copy : 1; + uint64_t internal_scom_error : 1; + uint64_t spare_fir31 : 1; + uint64_t spare_fir30 : 1; + uint64_t dir_purge_ce : 1; + uint64_t srb_buffer_sue : 1; + uint64_t srb_buffer_ue : 1; + uint64_t srb_buffer_ce : 1; + uint64_t occ_inband_write_error : 1; + uint64_t occ_inband_read_error : 1; + uint64_t host_inband_write_error : 1; + uint64_t host_inband_read_error : 1; + uint64_t emergency_throttle_set : 1; + uint64_t edram_error : 1; + uint64_t lru_error : 1; + uint64_t dir_all_members_deleted : 1; + uint64_t dir_member_deleted : 1; + uint64_t dir_ue : 1; + uint64_t dir_ce : 1; + uint64_t cache_co_sue : 1; + uint64_t cache_co_ue : 1; + uint64_t cache_co_ce : 1; + uint64_t cache_srw_sue : 1; + uint64_t cache_srw_ue : 1; + uint64_t cache_srw_ce : 1; + uint64_t int_parity_error : 1; + uint64_t int_buffer_sue : 1; + uint64_t int_buffer_ue : 1; + uint64_t int_buffer_ce : 1; + uint64_t internal_timeout : 1; + uint64_t external_timeout : 1; + uint64_t invalid_address_error : 1; + uint64_t int_protocol_error : 1; + uint64_t host_protocol_error : 1; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbs_fir_reg_and_t; + + + +typedef union centaur_mbs_fir_reg_or { + + 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 host_protocol_error : 1; + uint64_t int_protocol_error : 1; + uint64_t invalid_address_error : 1; + uint64_t external_timeout : 1; + uint64_t internal_timeout : 1; + uint64_t int_buffer_ce : 1; + uint64_t int_buffer_ue : 1; + uint64_t int_buffer_sue : 1; + uint64_t int_parity_error : 1; + uint64_t cache_srw_ce : 1; + uint64_t cache_srw_ue : 1; + uint64_t cache_srw_sue : 1; + uint64_t cache_co_ce : 1; + uint64_t cache_co_ue : 1; + uint64_t cache_co_sue : 1; + uint64_t dir_ce : 1; + uint64_t dir_ue : 1; + uint64_t dir_member_deleted : 1; + uint64_t dir_all_members_deleted : 1; + uint64_t lru_error : 1; + uint64_t edram_error : 1; + uint64_t emergency_throttle_set : 1; + uint64_t host_inband_read_error : 1; + uint64_t host_inband_write_error : 1; + uint64_t occ_inband_read_error : 1; + uint64_t occ_inband_write_error : 1; + uint64_t srb_buffer_ce : 1; + uint64_t srb_buffer_ue : 1; + uint64_t srb_buffer_sue : 1; + uint64_t dir_purge_ce : 1; + uint64_t spare_fir30 : 1; + uint64_t spare_fir31 : 1; + uint64_t internal_scom_error : 1; + uint64_t internal_scom_error_copy : 1; + uint64_t _reserved0 : 30; +#else + uint64_t _reserved0 : 30; + uint64_t internal_scom_error_copy : 1; + uint64_t internal_scom_error : 1; + uint64_t spare_fir31 : 1; + uint64_t spare_fir30 : 1; + uint64_t dir_purge_ce : 1; + uint64_t srb_buffer_sue : 1; + uint64_t srb_buffer_ue : 1; + uint64_t srb_buffer_ce : 1; + uint64_t occ_inband_write_error : 1; + uint64_t occ_inband_read_error : 1; + uint64_t host_inband_write_error : 1; + uint64_t host_inband_read_error : 1; + uint64_t emergency_throttle_set : 1; + uint64_t edram_error : 1; + uint64_t lru_error : 1; + uint64_t dir_all_members_deleted : 1; + uint64_t dir_member_deleted : 1; + uint64_t dir_ue : 1; + uint64_t dir_ce : 1; + uint64_t cache_co_sue : 1; + uint64_t cache_co_ue : 1; + uint64_t cache_co_ce : 1; + uint64_t cache_srw_sue : 1; + uint64_t cache_srw_ue : 1; + uint64_t cache_srw_ce : 1; + uint64_t int_parity_error : 1; + uint64_t int_buffer_sue : 1; + uint64_t int_buffer_ue : 1; + uint64_t int_buffer_ce : 1; + uint64_t internal_timeout : 1; + uint64_t external_timeout : 1; + uint64_t invalid_address_error : 1; + uint64_t int_protocol_error : 1; + uint64_t host_protocol_error : 1; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbs_fir_reg_or_t; + + + +typedef union centaur_mbs_fir_mask_reg { + + 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 host_protocol_error : 1; + uint64_t int_protocol_error : 1; + uint64_t invalid_address_error : 1; + uint64_t external_timeout : 1; + uint64_t internal_timeout : 1; + uint64_t int_buffer_ce : 1; + uint64_t int_buffer_ue : 1; + uint64_t int_buffer_sue : 1; + uint64_t int_parity_error : 1; + uint64_t cache_srw_ce : 1; + uint64_t cache_srw_ue : 1; + uint64_t cache_srw_sue : 1; + uint64_t cache_co_ce : 1; + uint64_t cache_co_ue : 1; + uint64_t cache_co_sue : 1; + uint64_t dir_ce : 1; + uint64_t dir_ue : 1; + uint64_t dir_member_deleted : 1; + uint64_t dir_all_members_deleted : 1; + uint64_t lru_error : 1; + uint64_t edram_error : 1; + uint64_t emergency_throttle_set : 1; + uint64_t host_inband_read_error : 1; + uint64_t host_inband_write_error : 1; + uint64_t occ_inband_read_error : 1; + uint64_t occ_inband_write_error : 1; + uint64_t srb_buffer_ce : 1; + uint64_t srb_buffer_ue : 1; + uint64_t srb_buffer_sue : 1; + uint64_t dir_purge_ce : 1; + uint64_t spare_fir30 : 1; + uint64_t spare_fir31 : 1; + uint64_t internal_scom_error : 1; + uint64_t internal_scom_error_copy : 1; + uint64_t _reserved0 : 30; +#else + uint64_t _reserved0 : 30; + uint64_t internal_scom_error_copy : 1; + uint64_t internal_scom_error : 1; + uint64_t spare_fir31 : 1; + uint64_t spare_fir30 : 1; + uint64_t dir_purge_ce : 1; + uint64_t srb_buffer_sue : 1; + uint64_t srb_buffer_ue : 1; + uint64_t srb_buffer_ce : 1; + uint64_t occ_inband_write_error : 1; + uint64_t occ_inband_read_error : 1; + uint64_t host_inband_write_error : 1; + uint64_t host_inband_read_error : 1; + uint64_t emergency_throttle_set : 1; + uint64_t edram_error : 1; + uint64_t lru_error : 1; + uint64_t dir_all_members_deleted : 1; + uint64_t dir_member_deleted : 1; + uint64_t dir_ue : 1; + uint64_t dir_ce : 1; + uint64_t cache_co_sue : 1; + uint64_t cache_co_ue : 1; + uint64_t cache_co_ce : 1; + uint64_t cache_srw_sue : 1; + uint64_t cache_srw_ue : 1; + uint64_t cache_srw_ce : 1; + uint64_t int_parity_error : 1; + uint64_t int_buffer_sue : 1; + uint64_t int_buffer_ue : 1; + uint64_t int_buffer_ce : 1; + uint64_t internal_timeout : 1; + uint64_t external_timeout : 1; + uint64_t invalid_address_error : 1; + uint64_t int_protocol_error : 1; + uint64_t host_protocol_error : 1; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbs_fir_mask_reg_t; + + + +typedef union centaur_mbs_fir_mask_reg_and { + + 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 host_protocol_error : 1; + uint64_t int_protocol_error : 1; + uint64_t invalid_address_error : 1; + uint64_t external_timeout : 1; + uint64_t internal_timeout : 1; + uint64_t int_buffer_ce : 1; + uint64_t int_buffer_ue : 1; + uint64_t int_buffer_sue : 1; + uint64_t int_parity_error : 1; + uint64_t cache_srw_ce : 1; + uint64_t cache_srw_ue : 1; + uint64_t cache_srw_sue : 1; + uint64_t cache_co_ce : 1; + uint64_t cache_co_ue : 1; + uint64_t cache_co_sue : 1; + uint64_t dir_ce : 1; + uint64_t dir_ue : 1; + uint64_t dir_member_deleted : 1; + uint64_t dir_all_members_deleted : 1; + uint64_t lru_error : 1; + uint64_t edram_error : 1; + uint64_t emergency_throttle_set : 1; + uint64_t host_inband_read_error : 1; + uint64_t host_inband_write_error : 1; + uint64_t occ_inband_read_error : 1; + uint64_t occ_inband_write_error : 1; + uint64_t srb_buffer_ce : 1; + uint64_t srb_buffer_ue : 1; + uint64_t srb_buffer_sue : 1; + uint64_t dir_purge_ce : 1; + uint64_t spare_fir30 : 1; + uint64_t spare_fir31 : 1; + uint64_t internal_scom_error : 1; + uint64_t internal_scom_error_copy : 1; + uint64_t _reserved0 : 30; +#else + uint64_t _reserved0 : 30; + uint64_t internal_scom_error_copy : 1; + uint64_t internal_scom_error : 1; + uint64_t spare_fir31 : 1; + uint64_t spare_fir30 : 1; + uint64_t dir_purge_ce : 1; + uint64_t srb_buffer_sue : 1; + uint64_t srb_buffer_ue : 1; + uint64_t srb_buffer_ce : 1; + uint64_t occ_inband_write_error : 1; + uint64_t occ_inband_read_error : 1; + uint64_t host_inband_write_error : 1; + uint64_t host_inband_read_error : 1; + uint64_t emergency_throttle_set : 1; + uint64_t edram_error : 1; + uint64_t lru_error : 1; + uint64_t dir_all_members_deleted : 1; + uint64_t dir_member_deleted : 1; + uint64_t dir_ue : 1; + uint64_t dir_ce : 1; + uint64_t cache_co_sue : 1; + uint64_t cache_co_ue : 1; + uint64_t cache_co_ce : 1; + uint64_t cache_srw_sue : 1; + uint64_t cache_srw_ue : 1; + uint64_t cache_srw_ce : 1; + uint64_t int_parity_error : 1; + uint64_t int_buffer_sue : 1; + uint64_t int_buffer_ue : 1; + uint64_t int_buffer_ce : 1; + uint64_t internal_timeout : 1; + uint64_t external_timeout : 1; + uint64_t invalid_address_error : 1; + uint64_t int_protocol_error : 1; + uint64_t host_protocol_error : 1; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbs_fir_mask_reg_and_t; + + + +typedef union centaur_mbs_fir_mask_reg_or { + + 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 host_protocol_error : 1; + uint64_t int_protocol_error : 1; + uint64_t invalid_address_error : 1; + uint64_t external_timeout : 1; + uint64_t internal_timeout : 1; + uint64_t int_buffer_ce : 1; + uint64_t int_buffer_ue : 1; + uint64_t int_buffer_sue : 1; + uint64_t int_parity_error : 1; + uint64_t cache_srw_ce : 1; + uint64_t cache_srw_ue : 1; + uint64_t cache_srw_sue : 1; + uint64_t cache_co_ce : 1; + uint64_t cache_co_ue : 1; + uint64_t cache_co_sue : 1; + uint64_t dir_ce : 1; + uint64_t dir_ue : 1; + uint64_t dir_member_deleted : 1; + uint64_t dir_all_members_deleted : 1; + uint64_t lru_error : 1; + uint64_t edram_error : 1; + uint64_t emergency_throttle_set : 1; + uint64_t host_inband_read_error : 1; + uint64_t host_inband_write_error : 1; + uint64_t occ_inband_read_error : 1; + uint64_t occ_inband_write_error : 1; + uint64_t srb_buffer_ce : 1; + uint64_t srb_buffer_ue : 1; + uint64_t srb_buffer_sue : 1; + uint64_t dir_purge_ce : 1; + uint64_t spare_fir30 : 1; + uint64_t spare_fir31 : 1; + uint64_t internal_scom_error : 1; + uint64_t internal_scom_error_copy : 1; + uint64_t _reserved0 : 30; +#else + uint64_t _reserved0 : 30; + uint64_t internal_scom_error_copy : 1; + uint64_t internal_scom_error : 1; + uint64_t spare_fir31 : 1; + uint64_t spare_fir30 : 1; + uint64_t dir_purge_ce : 1; + uint64_t srb_buffer_sue : 1; + uint64_t srb_buffer_ue : 1; + uint64_t srb_buffer_ce : 1; + uint64_t occ_inband_write_error : 1; + uint64_t occ_inband_read_error : 1; + uint64_t host_inband_write_error : 1; + uint64_t host_inband_read_error : 1; + uint64_t emergency_throttle_set : 1; + uint64_t edram_error : 1; + uint64_t lru_error : 1; + uint64_t dir_all_members_deleted : 1; + uint64_t dir_member_deleted : 1; + uint64_t dir_ue : 1; + uint64_t dir_ce : 1; + uint64_t cache_co_sue : 1; + uint64_t cache_co_ue : 1; + uint64_t cache_co_ce : 1; + uint64_t cache_srw_sue : 1; + uint64_t cache_srw_ue : 1; + uint64_t cache_srw_ce : 1; + uint64_t int_parity_error : 1; + uint64_t int_buffer_sue : 1; + uint64_t int_buffer_ue : 1; + uint64_t int_buffer_ce : 1; + uint64_t internal_timeout : 1; + uint64_t external_timeout : 1; + uint64_t invalid_address_error : 1; + uint64_t int_protocol_error : 1; + uint64_t host_protocol_error : 1; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbs_fir_mask_reg_or_t; + + + +typedef union centaur_mbs_fir_action0_reg { + + 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 host_protocol_error : 1; + uint64_t int_protocol_error : 1; + uint64_t invalid_address_error : 1; + uint64_t external_timeout : 1; + uint64_t internal_timeout : 1; + uint64_t int_buffer_ce : 1; + uint64_t int_buffer_ue : 1; + uint64_t int_buffer_sue : 1; + uint64_t int_parity_error : 1; + uint64_t cache_srw_ce : 1; + uint64_t cache_srw_ue : 1; + uint64_t cache_srw_sue : 1; + uint64_t cache_co_ce : 1; + uint64_t cache_co_ue : 1; + uint64_t cache_co_sue : 1; + uint64_t dir_ce : 1; + uint64_t dir_ue : 1; + uint64_t dir_member_deleted : 1; + uint64_t dir_all_members_deleted : 1; + uint64_t lru_error : 1; + uint64_t edram_error : 1; + uint64_t emergency_throttle_set : 1; + uint64_t host_inband_read_error : 1; + uint64_t host_inband_write_error : 1; + uint64_t occ_inband_read_error : 1; + uint64_t occ_inband_write_error : 1; + uint64_t srb_buffer_ce : 1; + uint64_t srb_buffer_ue : 1; + uint64_t srb_buffer_sue : 1; + uint64_t dir_purge_ce : 1; + uint64_t spare_fir30 : 1; + uint64_t spare_fir31 : 1; + uint64_t internal_scom_error : 1; + uint64_t internal_scom_error_copy : 1; + uint64_t _reserved0 : 30; +#else + uint64_t _reserved0 : 30; + uint64_t internal_scom_error_copy : 1; + uint64_t internal_scom_error : 1; + uint64_t spare_fir31 : 1; + uint64_t spare_fir30 : 1; + uint64_t dir_purge_ce : 1; + uint64_t srb_buffer_sue : 1; + uint64_t srb_buffer_ue : 1; + uint64_t srb_buffer_ce : 1; + uint64_t occ_inband_write_error : 1; + uint64_t occ_inband_read_error : 1; + uint64_t host_inband_write_error : 1; + uint64_t host_inband_read_error : 1; + uint64_t emergency_throttle_set : 1; + uint64_t edram_error : 1; + uint64_t lru_error : 1; + uint64_t dir_all_members_deleted : 1; + uint64_t dir_member_deleted : 1; + uint64_t dir_ue : 1; + uint64_t dir_ce : 1; + uint64_t cache_co_sue : 1; + uint64_t cache_co_ue : 1; + uint64_t cache_co_ce : 1; + uint64_t cache_srw_sue : 1; + uint64_t cache_srw_ue : 1; + uint64_t cache_srw_ce : 1; + uint64_t int_parity_error : 1; + uint64_t int_buffer_sue : 1; + uint64_t int_buffer_ue : 1; + uint64_t int_buffer_ce : 1; + uint64_t internal_timeout : 1; + uint64_t external_timeout : 1; + uint64_t invalid_address_error : 1; + uint64_t int_protocol_error : 1; + uint64_t host_protocol_error : 1; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbs_fir_action0_reg_t; + + + +typedef union centaur_mbs_firact1 { + + 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 host_protocol_error : 1; + uint64_t int_protocol_error : 1; + uint64_t invalid_address_error : 1; + uint64_t external_timeout : 1; + uint64_t internal_timeout : 1; + uint64_t int_buffer_ce : 1; + uint64_t int_buffer_ue : 1; + uint64_t int_buffer_sue : 1; + uint64_t int_parity_error : 1; + uint64_t cache_srw_ce : 1; + uint64_t cache_srw_ue : 1; + uint64_t cache_srw_sue : 1; + uint64_t cache_co_ce : 1; + uint64_t cache_co_ue : 1; + uint64_t cache_co_sue : 1; + uint64_t dir_ce : 1; + uint64_t dir_ue : 1; + uint64_t dir_member_deleted : 1; + uint64_t dir_all_members_deleted : 1; + uint64_t lru_error : 1; + uint64_t edram_error : 1; + uint64_t emergency_throttle_set : 1; + uint64_t host_inband_read_error : 1; + uint64_t host_inband_write_error : 1; + uint64_t occ_inband_read_error : 1; + uint64_t occ_inband_write_error : 1; + uint64_t srb_buffer_ce : 1; + uint64_t srb_buffer_ue : 1; + uint64_t srb_buffer_sue : 1; + uint64_t dir_purge_ce : 1; + uint64_t spare_fir30 : 1; + uint64_t spare_fir31 : 1; + uint64_t internal_scom_error : 1; + uint64_t internal_scom_error_copy : 1; + uint64_t _reserved0 : 30; +#else + uint64_t _reserved0 : 30; + uint64_t internal_scom_error_copy : 1; + uint64_t internal_scom_error : 1; + uint64_t spare_fir31 : 1; + uint64_t spare_fir30 : 1; + uint64_t dir_purge_ce : 1; + uint64_t srb_buffer_sue : 1; + uint64_t srb_buffer_ue : 1; + uint64_t srb_buffer_ce : 1; + uint64_t occ_inband_write_error : 1; + uint64_t occ_inband_read_error : 1; + uint64_t host_inband_write_error : 1; + uint64_t host_inband_read_error : 1; + uint64_t emergency_throttle_set : 1; + uint64_t edram_error : 1; + uint64_t lru_error : 1; + uint64_t dir_all_members_deleted : 1; + uint64_t dir_member_deleted : 1; + uint64_t dir_ue : 1; + uint64_t dir_ce : 1; + uint64_t cache_co_sue : 1; + uint64_t cache_co_ue : 1; + uint64_t cache_co_ce : 1; + uint64_t cache_srw_sue : 1; + uint64_t cache_srw_ue : 1; + uint64_t cache_srw_ce : 1; + uint64_t int_parity_error : 1; + uint64_t int_buffer_sue : 1; + uint64_t int_buffer_ue : 1; + uint64_t int_buffer_ce : 1; + uint64_t internal_timeout : 1; + uint64_t external_timeout : 1; + uint64_t invalid_address_error : 1; + uint64_t int_protocol_error : 1; + uint64_t host_protocol_error : 1; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbs_firact1_t; + + + +typedef union centaur_mbscfgq { + + 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 eccbp_exit_sel : 1; + uint64_t dram_ecc_bypass_dis : 1; + uint64_t mbs_scom_wat_trigger : 1; + uint64_t mbs_prq_ref_avoidance_en : 1; + uint64_t reserved4_6 : 3; + uint64_t occ_deadman_timer_sel : 4; + uint64_t sync_fsync_mba_strobe_en : 1; + uint64_t hca_timebase_op_mode : 1; + uint64_t hca_local_timer_inc_select : 3; + uint64_t mbs_01_rdtag_delay : 4; + uint64_t mbs_01_rdtag_force_dead_cycle : 1; + uint64_t sync_lat_pol_01 : 1; + uint64_t sync_lat_adj_01 : 2; + uint64_t mbs_23_rdtag_delay : 4; + uint64_t mbs_23_rdtag_force_dead_cycle : 1; + uint64_t sync_lat_pol_23 : 1; + uint64_t sync_lat_adj_23 : 2; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t sync_lat_adj_23 : 2; + uint64_t sync_lat_pol_23 : 1; + uint64_t mbs_23_rdtag_force_dead_cycle : 1; + uint64_t mbs_23_rdtag_delay : 4; + uint64_t sync_lat_adj_01 : 2; + uint64_t sync_lat_pol_01 : 1; + uint64_t mbs_01_rdtag_force_dead_cycle : 1; + uint64_t mbs_01_rdtag_delay : 4; + uint64_t hca_local_timer_inc_select : 3; + uint64_t hca_timebase_op_mode : 1; + uint64_t sync_fsync_mba_strobe_en : 1; + uint64_t occ_deadman_timer_sel : 4; + uint64_t reserved4_6 : 3; + uint64_t mbs_prq_ref_avoidance_en : 1; + uint64_t mbs_scom_wat_trigger : 1; + uint64_t dram_ecc_bypass_dis : 1; + uint64_t eccbp_exit_sel : 1; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbscfgq_t; + + + +typedef union centaur_mbsemerthroq { + + 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 emergency_throttle_ip : 1; + uint64_t _reserved0 : 63; +#else + uint64_t _reserved0 : 63; + uint64_t emergency_throttle_ip : 1; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbsemerthroq_t; + + + +typedef union centaur_mbsocc01hq { + + 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 occ_01_rd_hit : 32; + uint64_t occ_01_wr_hit : 32; +#else + uint64_t occ_01_wr_hit : 32; + uint64_t occ_01_rd_hit : 32; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbsocc01hq_t; + + + +typedef union centaur_mbsocc23hq { + + 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 occ_23_rd_hit : 32; + uint64_t occ_23_wr_hit : 32; +#else + uint64_t occ_23_wr_hit : 32; + uint64_t occ_23_rd_hit : 32; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbsocc23hq_t; + + + +typedef union centaur_mbsoccitcq { + + 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 occ_cent_idle_th_cnt : 32; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t occ_cent_idle_th_cnt : 32; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbsoccitcq_t; + + + +typedef union centaur_mbsoccscanq { + + 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 occ_01_spec_can : 32; + uint64_t occ_23_spec_can : 32; +#else + uint64_t occ_23_spec_can : 32; + uint64_t occ_01_spec_can : 32; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbsoccscanq_t; + + + +typedef union centaur_mbarpc0qn { + + 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 cfg_lp2_entry_req : 1; + uint64_t cfg_lp2_state : 1; + uint64_t cfg_min_max_domains_enable : 1; + uint64_t cfg_min_max_domains : 3; + uint64_t cfg_pup_avail : 5; + uint64_t cfg_pdn_pup : 5; + uint64_t cfg_pup_pdn : 5; + uint64_t reserved0 : 1; + uint64_t cfg_min_domain_reduction_enable : 1; + uint64_t cfg_min_domain_reduction_on_time : 10; + uint64_t cfg_pup_after_activate_wait_enable : 1; + uint64_t cfg_pup_after_activate_wait_time : 8; + uint64_t cfg_force_spare_pup : 1; + uint64_t _reserved0 : 21; +#else + uint64_t _reserved0 : 21; + uint64_t cfg_force_spare_pup : 1; + uint64_t cfg_pup_after_activate_wait_time : 8; + uint64_t cfg_pup_after_activate_wait_enable : 1; + uint64_t cfg_min_domain_reduction_on_time : 10; + uint64_t cfg_min_domain_reduction_enable : 1; + uint64_t reserved0 : 1; + uint64_t cfg_pup_pdn : 5; + uint64_t cfg_pdn_pup : 5; + uint64_t cfg_pup_avail : 5; + uint64_t cfg_min_max_domains : 3; + uint64_t cfg_min_max_domains_enable : 1; + uint64_t cfg_lp2_state : 1; + uint64_t cfg_lp2_entry_req : 1; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbarpc0qn_t; + + + +typedef union centaur_mba_farb3qn { + + 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 cfg_nm_n_per_mba : 15; + uint64_t cfg_nm_n_per_chip : 16; + uint64_t cfg_nm_m : 14; + uint64_t cfg_nm_ras_weight : 3; + uint64_t cfg_nm_cas_weight : 3; + uint64_t cfg_nm_per_slot_enabled : 1; + uint64_t cfg_nm_count_other_mba_dis : 1; + uint64_t _reserved0 : 11; +#else + uint64_t _reserved0 : 11; + uint64_t cfg_nm_count_other_mba_dis : 1; + uint64_t cfg_nm_per_slot_enabled : 1; + uint64_t cfg_nm_cas_weight : 3; + uint64_t cfg_nm_ras_weight : 3; + uint64_t cfg_nm_m : 14; + uint64_t cfg_nm_n_per_chip : 16; + uint64_t cfg_nm_n_per_mba : 15; +#endif // _BIG_ENDIAN + } fields; +} centaur_mba_farb3qn_t; + + + +typedef union centaur_mbapcn { + + 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 mode_hp_sub_cnt : 1; + uint64_t mode_lp_sub_cnt : 1; + uint64_t mode_static_idle_dly : 5; + uint64_t mode_emer_min_max_domain : 3; + uint64_t mode_pup_all_wr_pending : 2; + uint64_t mode_lp_ref_sim_enq : 1; + uint64_t _reserved0 : 51; +#else + uint64_t _reserved0 : 51; + uint64_t mode_lp_ref_sim_enq : 1; + uint64_t mode_pup_all_wr_pending : 2; + uint64_t mode_emer_min_max_domain : 3; + uint64_t mode_static_idle_dly : 5; + uint64_t mode_lp_sub_cnt : 1; + uint64_t mode_hp_sub_cnt : 1; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbapcn_t; + + + +typedef union centaur_mbasrqn { + + 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 emergency_m : 14; + uint64_t emergency_n : 15; + uint64_t _reserved0 : 35; +#else + uint64_t _reserved0 : 35; + uint64_t emergency_n : 15; + uint64_t emergency_m : 14; +#endif // _BIG_ENDIAN + } fields; +} centaur_mbasrqn_t; + + + +typedef union centaur_pmu0qn { + + 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 read_count : 32; + uint64_t write_count : 32; +#else + uint64_t write_count : 32; + uint64_t read_count : 32; +#endif // _BIG_ENDIAN + } fields; +} centaur_pmu0qn_t; + + + +typedef union centaur_pmu1qn { + + 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 activate_count : 32; + uint64_t pu_counts : 32; +#else + uint64_t pu_counts : 32; + uint64_t activate_count : 32; +#endif // _BIG_ENDIAN + } fields; +} centaur_pmu1qn_t; + + + +typedef union centaur_pmu2qn { + + 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 frame_count : 32; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t frame_count : 32; +#endif // _BIG_ENDIAN + } fields; +} centaur_pmu2qn_t; + + + +typedef union centaur_pmu3qn { + + 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 low_idle_threshold : 16; + uint64_t med_idle_threshold : 16; + uint64_t high_idle_threshold : 32; +#else + uint64_t high_idle_threshold : 32; + uint64_t med_idle_threshold : 16; + uint64_t low_idle_threshold : 16; +#endif // _BIG_ENDIAN + } fields; +} centaur_pmu3qn_t; + + + +typedef union centaur_pmu4qn { + + 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 base_idle_count : 32; + uint64_t low_idle_count : 32; +#else + uint64_t low_idle_count : 32; + uint64_t base_idle_count : 32; +#endif // _BIG_ENDIAN + } fields; +} centaur_pmu4qn_t; + + + +typedef union centaur_pmu5qn { + + 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 med_idle_count : 32; + uint64_t high_idle_count : 32; +#else + uint64_t high_idle_count : 32; + uint64_t med_idle_count : 32; +#endif // _BIG_ENDIAN + } fields; +} centaur_pmu5qn_t; + + + +typedef union centaur_pmu6qn { + + 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 total_gap_counts : 18; + uint64_t specific_gap_counts : 18; + uint64_t gap_length_adder : 3; + uint64_t specific_gap_condition : 4; + uint64_t cmd_to_cmd_count : 18; + uint64_t command_pattern_to_count : 3; +#else + uint64_t command_pattern_to_count : 3; + uint64_t cmd_to_cmd_count : 18; + uint64_t specific_gap_condition : 4; + uint64_t gap_length_adder : 3; + uint64_t specific_gap_counts : 18; + uint64_t total_gap_counts : 18; +#endif // _BIG_ENDIAN + } fields; +} centaur_pmu6qn_t; + + + +typedef union centaur_sensor_cache_data0_3 { + + 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 crittrip0 : 1; + uint64_t abovetrip0 : 1; + uint64_t belowtrip0 : 1; + uint64_t signbit0 : 1; + uint64_t temperature0 : 8; + uint64_t temp_frac0 : 2; + uint64_t status0 : 2; + uint64_t crittrip1 : 1; + uint64_t abovetrip1 : 1; + uint64_t belowtrip1 : 1; + uint64_t signbit1 : 1; + uint64_t temperature1 : 8; + uint64_t temp_frac1 : 2; + uint64_t status1 : 2; + uint64_t crittrip2 : 1; + uint64_t abovetrip2 : 1; + uint64_t belowtrip2 : 1; + uint64_t signbit2 : 1; + uint64_t temperature2 : 8; + uint64_t temp_frac2 : 2; + uint64_t status2 : 2; + uint64_t crittrip3 : 1; + uint64_t abovetrip3 : 1; + uint64_t belowtrip3 : 1; + uint64_t signbit3 : 1; + uint64_t temperature3 : 8; + uint64_t temp_frac3 : 2; + uint64_t status3 : 2; +#else + uint64_t status3 : 2; + uint64_t temp_frac3 : 2; + uint64_t temperature3 : 8; + uint64_t signbit3 : 1; + uint64_t belowtrip3 : 1; + uint64_t abovetrip3 : 1; + uint64_t crittrip3 : 1; + uint64_t status2 : 2; + uint64_t temp_frac2 : 2; + uint64_t temperature2 : 8; + uint64_t signbit2 : 1; + uint64_t belowtrip2 : 1; + uint64_t abovetrip2 : 1; + uint64_t crittrip2 : 1; + uint64_t status1 : 2; + uint64_t temp_frac1 : 2; + uint64_t temperature1 : 8; + uint64_t signbit1 : 1; + uint64_t belowtrip1 : 1; + uint64_t abovetrip1 : 1; + uint64_t crittrip1 : 1; + uint64_t status0 : 2; + uint64_t temp_frac0 : 2; + uint64_t temperature0 : 8; + uint64_t signbit0 : 1; + uint64_t belowtrip0 : 1; + uint64_t abovetrip0 : 1; + uint64_t crittrip0 : 1; +#endif // _BIG_ENDIAN + } fields; +} centaur_sensor_cache_data0_3_t; + + + +typedef union centaur_sensor_cache_data4_7 { + + 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 crittrip4 : 1; + uint64_t abovetrip4 : 1; + uint64_t belowtrip4 : 1; + uint64_t signbit4 : 1; + uint64_t temperature4 : 8; + uint64_t temp_frac4 : 2; + uint64_t status4 : 2; + uint64_t crittrip5 : 1; + uint64_t abovetrip5 : 1; + uint64_t belowtrip5 : 1; + uint64_t signbit5 : 1; + uint64_t temperature5 : 8; + uint64_t temp_frac5 : 2; + uint64_t status5 : 2; + uint64_t crittrip6 : 1; + uint64_t abovetrip6 : 1; + uint64_t belowtrip6 : 1; + uint64_t signbit6 : 1; + uint64_t temperature6 : 8; + uint64_t temp_frac6 : 2; + uint64_t status6 : 2; + uint64_t crittrip7 : 1; + uint64_t abovetrip7 : 1; + uint64_t belowtrip7 : 1; + uint64_t signbit7 : 1; + uint64_t temperature7 : 8; + uint64_t temp_frac7 : 2; + uint64_t status7 : 2; +#else + uint64_t status7 : 2; + uint64_t temp_frac7 : 2; + uint64_t temperature7 : 8; + uint64_t signbit7 : 1; + uint64_t belowtrip7 : 1; + uint64_t abovetrip7 : 1; + uint64_t crittrip7 : 1; + uint64_t status6 : 2; + uint64_t temp_frac6 : 2; + uint64_t temperature6 : 8; + uint64_t signbit6 : 1; + uint64_t belowtrip6 : 1; + uint64_t abovetrip6 : 1; + uint64_t crittrip6 : 1; + uint64_t status5 : 2; + uint64_t temp_frac5 : 2; + uint64_t temperature5 : 8; + uint64_t signbit5 : 1; + uint64_t belowtrip5 : 1; + uint64_t abovetrip5 : 1; + uint64_t crittrip5 : 1; + uint64_t status4 : 2; + uint64_t temp_frac4 : 2; + uint64_t temperature4 : 8; + uint64_t signbit4 : 1; + uint64_t belowtrip4 : 1; + uint64_t abovetrip4 : 1; + uint64_t crittrip4 : 1; +#endif // _BIG_ENDIAN + } fields; +} centaur_sensor_cache_data4_7_t; + + + +typedef union centaur_dts_thermal_sensor_results { + + 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 dts0 : 12; + uint64_t thermal_trip0 : 2; + uint64_t spare0 : 1; + uint64_t valid0 : 1; + uint64_t dts1 : 12; + uint64_t thermal_trip1 : 2; + uint64_t spare1 : 1; + uint64_t valid1 : 1; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t valid1 : 1; + uint64_t spare1 : 1; + uint64_t thermal_trip1 : 2; + uint64_t dts1 : 12; + uint64_t valid0 : 1; + uint64_t spare0 : 1; + uint64_t thermal_trip0 : 2; + uint64_t dts0 : 12; +#endif // _BIG_ENDIAN + } fields; +} centaur_dts_thermal_sensor_results_t; + + +#endif // __ASSEMBLER__ +#endif // __CENTAUR_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/centaur_register_addresses.h b/src/ssx/pgp/registers/centaur_register_addresses.h new file mode 100755 index 0000000..7c9c095 --- /dev/null +++ b/src/ssx/pgp/registers/centaur_register_addresses.h @@ -0,0 +1,66 @@ +#ifndef __CENTAUR_REGISTER_ADDRESSES_H__ +#define __CENTAUR_REGISTER_ADDRESSES_H__ + +// $Id: centaur_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/centaur_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file centaur_register_addresses.h +/// \brief Symbolic addresses for the CENTAUR unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define CENTAUR_PIB_BASE 0 +#define CENTAUR_DEVICE_ID 0x000f000f +#define CENTAUR_MBS_FIR_REG 0x02011400 +#define CENTAUR_MBS_FIR_REG_AND 0x02011401 +#define CENTAUR_MBS_FIR_REG_OR 0x02011402 +#define CENTAUR_MBS_FIR_MASK_REG 0x02011403 +#define CENTAUR_MBS_FIR_MASK_REG_AND 0x02011404 +#define CENTAUR_MBS_FIR_MASK_REG_OR 0x02011405 +#define CENTAUR_MBS_FIR_ACTION0_REG 0x02011406 +#define CENTAUR_MBS_FIRACT1 0x02011407 +#define CENTAUR_MBSCFGQ 0x02011411 +#define CENTAUR_MBSEMERTHROQ 0x0201142d +#define CENTAUR_MBSOCC01HQ 0x02011429 +#define CENTAUR_MBSOCC23HQ 0x0201142a +#define CENTAUR_MBSOCCITCQ 0x02011428 +#define CENTAUR_MBSOCCSCANQ 0x0201142b +#define CENTAUR_MBARPC0QN(n) (CENTAUR_MBARPC0Q0 + ((CENTAUR_MBARPC0Q1 - CENTAUR_MBARPC0Q0) * (n))) +#define CENTAUR_MBARPC0Q0 0x03010434 +#define CENTAUR_MBARPC0Q1 0x03010c34 +#define CENTAUR_MBA_FARB3QN(n) (CENTAUR_MBA_FARB3Q0 + ((CENTAUR_MBA_FARB3Q1 - CENTAUR_MBA_FARB3Q0) * (n))) +#define CENTAUR_MBA_FARB3Q0 0x03010416 +#define CENTAUR_MBA_FARB3Q1 0x03010c16 +#define CENTAUR_PMU0QN(n) (CENTAUR_PMU0Q0 + ((CENTAUR_PMU0Q1 - CENTAUR_PMU0Q0) * (n))) +#define CENTAUR_PMU0Q0 0x03010437 +#define CENTAUR_PMU0Q1 0x03010c37 +#define CENTAUR_PMU1QN(n) (CENTAUR_PMU1Q0 + ((CENTAUR_PMU1Q1 - CENTAUR_PMU1Q0) * (n))) +#define CENTAUR_PMU1Q0 0x03010438 +#define CENTAUR_PMU1Q1 0x03010c38 +#define CENTAUR_PMU2QN(n) (CENTAUR_PMU2Q0 + ((CENTAUR_PMU2Q1 - CENTAUR_PMU2Q0) * (n))) +#define CENTAUR_PMU2Q0 0x03010439 +#define CENTAUR_PMU2Q1 0x03010c39 +#define CENTAUR_PMU3QN(n) (CENTAUR_PMU3Q0 + ((CENTAUR_PMU3Q1 - CENTAUR_PMU3Q0) * (n))) +#define CENTAUR_PMU3Q0 0x0301043a +#define CENTAUR_PMU3Q1 0x03010c3a +#define CENTAUR_PMU4QN(n) (CENTAUR_PMU4Q0 + ((CENTAUR_PMU4Q1 - CENTAUR_PMU4Q0) * (n))) +#define CENTAUR_PMU4Q0 0x0301043b +#define CENTAUR_PMU4Q1 0x03010c3b +#define CENTAUR_PMU5QN(n) (CENTAUR_PMU5Q0 + ((CENTAUR_PMU5Q1 - CENTAUR_PMU5Q0) * (n))) +#define CENTAUR_PMU5Q0 0x0301043c +#define CENTAUR_PMU5Q1 0x03010c3c +#define CENTAUR_PMU6QN(n) (CENTAUR_PMU6Q0 + ((CENTAUR_PMU6Q1 - CENTAUR_PMU6Q0) * (n))) +#define CENTAUR_PMU6Q0 0x0301043d +#define CENTAUR_PMU6Q1 0x03010c3d +#define CENTAUR_SENSOR_CACHE_DATA0_3 0x020115ca +#define CENTAUR_SENSOR_CACHE_DATA4_7 0x020115cb +#define CENTAUR_DTS_THERMAL_SENSOR_RESULTS 0x02050000 + +#endif // __CENTAUR_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/fasti2c_firmware_registers.h b/src/ssx/pgp/registers/fasti2c_firmware_registers.h new file mode 100644 index 0000000..4390508 --- /dev/null +++ b/src/ssx/pgp/registers/fasti2c_firmware_registers.h @@ -0,0 +1,232 @@ +#ifndef __FASTI2C_FIRMWARE_REGISTERS_H__ +#define __FASTI2C_FIRMWARE_REGISTERS_H__ + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +// $Id: fasti2c_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $ + +/// \file fasti2c_firmware_registers.h +/// \brief C register structs for the FASTI2C unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#include <stdint.h> + + + +typedef union fasti2c_control { + + 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; +} fasti2c_control_t; + + + +typedef union fasti2c_reset { + + 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; +} fasti2c_reset_t; + + + +typedef union fasti2c_status { + + 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; +} fasti2c_status_t; + + + +typedef union fasti2c_data { + + 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; +} fasti2c_data_t; + + + +typedef union fasti2c_ecc_start { + + 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; +} fasti2c_ecc_start_t; + + + +typedef union fasti2c_ecc_stop { + + 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; +} fasti2c_ecc_stop_t; + + +#endif // __ASSEMBLER__ +#endif // __FASTI2C_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/fasti2c_register_addresses.h b/src/ssx/pgp/registers/fasti2c_register_addresses.h new file mode 100644 index 0000000..b034831 --- /dev/null +++ b/src/ssx/pgp/registers/fasti2c_register_addresses.h @@ -0,0 +1,27 @@ +#ifndef __FASTI2C_REGISTER_ADDRESSES_H__ +#define __FASTI2C_REGISTER_ADDRESSES_H__ + +// $Id: fasti2c_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $ + +/// \file fasti2c_register_addresses.h +/// \brief Symbolic addresses for the FASTI2C unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define FASTI2C_LPCM_PIB_BASE 0x0000000b +#define FASTI2C_CONTROL_OFFSET 0x00000000 +#define FASTI2C_LPCM_CONTROL 0x0000000b +#define FASTI2C_RESET_OFFSET 0x00000001 +#define FASTI2C_LPCM_RESET 0x0000000c +#define FASTI2C_STATUS_OFFSET 0x00000002 +#define FASTI2C_LPCM_STATUS 0x0000000d +#define FASTI2C_DATA_OFFSET 0x00000003 +#define FASTI2C_LPCM_DATA 0x0000000e +#define FASTI2C_ECC_START_OFFSET 0x00000004 +#define FASTI2C_LPCM_ECC_START 0x0000000f +#define FASTI2C_ECC_STOP_OFFSET 0x00000005 +#define FASTI2C_LPCM_ECC_STOP 0x00000010 + +#endif // __FASTI2C_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/i2cengine_firmware_registers.h b/src/ssx/pgp/registers/i2cengine_firmware_registers.h new file mode 100644 index 0000000..ed02574 --- /dev/null +++ b/src/ssx/pgp/registers/i2cengine_firmware_registers.h @@ -0,0 +1,710 @@ +#ifndef __I2CENGINE_FIRMWARE_REGISTERS_H__ +#define __I2CENGINE_FIRMWARE_REGISTERS_H__ + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +// $Id: i2cengine_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ + +/// \file i2cengine_firmware_registers.h +/// \brief C register structs for the I2CENGINE unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#include <stdint.h> + + + +typedef union i2cengine_fast_control { + + 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; +} i2cengine_fast_control_t; + + + +typedef union i2cengine_fast_reset { + + 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; +} i2cengine_fast_reset_t; + + + +typedef union i2cengine_fast_status { + + 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; +} i2cengine_fast_status_t; + + + +typedef union i2cengine_fast_data { + + 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; +} i2cengine_fast_data_t; + + + +typedef union i2cengine_fifo_byte { + + 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 data : 32; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t data : 32; +#endif // _BIG_ENDIAN + } fields; +} i2cengine_fifo_byte_t; + + + +typedef union i2cengine_command { + + 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 not_used : 1; + uint64_t reserved : 4; + uint64_t device_address : 7; + uint64_t read_not_write : 1; + uint64_t length_bytes : 16; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t length_bytes : 16; + uint64_t read_not_write : 1; + uint64_t device_address : 7; + uint64_t reserved : 4; + uint64_t not_used : 1; + uint64_t read_continue : 1; + uint64_t with_address : 1; + uint64_t with_start : 1; +#endif // _BIG_ENDIAN + } fields; +} i2cengine_command_t; + + + +typedef union i2cengine_mode { + + 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 bit_rate_divisor : 15; + uint64_t _reserved0 : 1; + uint64_t port_number : 6; + uint64_t reserved : 6; + uint64_t enhanced_mode : 1; + uint64_t diagnostic_mode : 1; + uint64_t pacing_allow_mode : 1; + uint64_t wrap_mode : 1; + uint64_t _reserved1 : 32; +#else + uint64_t _reserved1 : 32; + uint64_t wrap_mode : 1; + uint64_t pacing_allow_mode : 1; + uint64_t diagnostic_mode : 1; + uint64_t enhanced_mode : 1; + uint64_t reserved : 6; + uint64_t port_number : 6; + uint64_t _reserved0 : 1; + uint64_t bit_rate_divisor : 15; +#endif // _BIG_ENDIAN + } fields; +} i2cengine_mode_t; + + + +typedef union i2cengine_watermark { + + 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 reserved : 15; + uint64_t _reserved0 : 1; + uint64_t high_water_mark : 4; + uint64_t reserved1 : 4; + uint64_t low_water_mark : 4; + uint64_t reserved2 : 4; + uint64_t _reserved1 : 32; +#else + uint64_t _reserved1 : 32; + uint64_t reserved2 : 4; + uint64_t low_water_mark : 4; + uint64_t reserved1 : 4; + uint64_t high_water_mark : 4; + uint64_t _reserved0 : 1; + uint64_t reserved : 15; +#endif // _BIG_ENDIAN + } fields; +} i2cengine_watermark_t; + + + +typedef union i2cengine_interrupt_mask { + + 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 reserved : 16; + uint64_t invalid_command : 1; + uint64_t lbus_parity_error : 1; + uint64_t back_end_overrun_error : 1; + uint64_t back_end_access_error : 1; + uint64_t arbitration_lost_error : 1; + uint64_t nack_received_error : 1; + uint64_t data_request : 1; + uint64_t command_complete : 1; + uint64_t stop_error : 1; + uint64_t i2c_busy : 1; + uint64_t not_i2c_busy : 1; + uint64_t reserved1 : 1; + uint64_t scl_eq_1 : 1; + uint64_t scl_eq_0 : 1; + uint64_t sda_eq_1 : 1; + uint64_t sda_eq_0 : 1; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t sda_eq_0 : 1; + uint64_t sda_eq_1 : 1; + uint64_t scl_eq_0 : 1; + uint64_t scl_eq_1 : 1; + uint64_t reserved1 : 1; + uint64_t not_i2c_busy : 1; + uint64_t i2c_busy : 1; + uint64_t stop_error : 1; + uint64_t command_complete : 1; + uint64_t data_request : 1; + uint64_t nack_received_error : 1; + uint64_t arbitration_lost_error : 1; + uint64_t back_end_access_error : 1; + uint64_t back_end_overrun_error : 1; + uint64_t lbus_parity_error : 1; + uint64_t invalid_command : 1; + uint64_t reserved : 16; +#endif // _BIG_ENDIAN + } fields; +} i2cengine_interrupt_mask_t; + + + +typedef union i2cengine_interrupt_condition { + + 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 reserved : 16; + uint64_t invalid_command : 1; + uint64_t lbus_parity_error : 1; + uint64_t back_end_overrun_error : 1; + uint64_t back_end_access_error : 1; + uint64_t arbitration_lost_error : 1; + uint64_t nack_received_error : 1; + uint64_t data_request : 1; + uint64_t command_complete : 1; + uint64_t stop_error : 1; + uint64_t i2c_busy : 1; + uint64_t not_i2c_busy : 1; + uint64_t reserved1 : 1; + uint64_t scl_eq_1 : 1; + uint64_t scl_eq_0 : 1; + uint64_t sda_eq_1 : 1; + uint64_t sda_eq_0 : 1; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t sda_eq_0 : 1; + uint64_t sda_eq_1 : 1; + uint64_t scl_eq_0 : 1; + uint64_t scl_eq_1 : 1; + uint64_t reserved1 : 1; + uint64_t not_i2c_busy : 1; + uint64_t i2c_busy : 1; + uint64_t stop_error : 1; + uint64_t command_complete : 1; + uint64_t data_request : 1; + uint64_t nack_received_error : 1; + uint64_t arbitration_lost_error : 1; + uint64_t back_end_access_error : 1; + uint64_t back_end_overrun_error : 1; + uint64_t lbus_parity_error : 1; + uint64_t invalid_command : 1; + uint64_t reserved : 16; +#endif // _BIG_ENDIAN + } fields; +} i2cengine_interrupt_condition_t; + + + +typedef union i2cengine_interrupts { + + 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 reserved : 16; + uint64_t invalid_command : 1; + uint64_t lbus_parity_error : 1; + uint64_t back_end_overrun_error : 1; + uint64_t back_end_access_error : 1; + uint64_t arbitration_lost_error : 1; + uint64_t nack_received_error : 1; + uint64_t data_request : 1; + uint64_t command_complete : 1; + uint64_t stop_error : 1; + uint64_t i2c_busy : 1; + uint64_t not_i2c_busy : 1; + uint64_t reserved1 : 1; + uint64_t scl_eq_1 : 1; + uint64_t scl_eq_0 : 1; + uint64_t sda_eq_1 : 1; + uint64_t sda_eq_0 : 1; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t sda_eq_0 : 1; + uint64_t sda_eq_1 : 1; + uint64_t scl_eq_0 : 1; + uint64_t scl_eq_1 : 1; + uint64_t reserved1 : 1; + uint64_t not_i2c_busy : 1; + uint64_t i2c_busy : 1; + uint64_t stop_error : 1; + uint64_t command_complete : 1; + uint64_t data_request : 1; + uint64_t nack_received_error : 1; + uint64_t arbitration_lost_error : 1; + uint64_t back_end_access_error : 1; + uint64_t back_end_overrun_error : 1; + uint64_t lbus_parity_error : 1; + uint64_t invalid_command : 1; + uint64_t reserved : 16; +#endif // _BIG_ENDIAN + } fields; +} i2cengine_interrupts_t; + + + +typedef union i2cengine_status { + + 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 invalid_command : 1; + uint64_t lbus_parity_error : 1; + uint64_t back_end_overrun_error : 1; + uint64_t back_end_access_error : 1; + uint64_t arbitration_lost_error : 1; + uint64_t nack_received_error : 1; + uint64_t data_request : 1; + uint64_t command_complete : 1; + uint64_t stop_error : 1; + uint64_t upper_threshold : 6; + uint64_t _reserved0 : 1; + uint64_t any_i2c_interrupt : 1; + uint64_t reserved1 : 3; + uint64_t scl_input_lvl : 1; + uint64_t sda_input_lvl : 1; + uint64_t i2c_port_busy : 1; + uint64_t i2c_interface_busy : 1; + uint64_t fifo_entry_count : 8; + uint64_t _reserved1 : 32; +#else + uint64_t _reserved1 : 32; + uint64_t fifo_entry_count : 8; + uint64_t i2c_interface_busy : 1; + uint64_t i2c_port_busy : 1; + uint64_t sda_input_lvl : 1; + uint64_t scl_input_lvl : 1; + uint64_t reserved1 : 3; + uint64_t any_i2c_interrupt : 1; + uint64_t _reserved0 : 1; + uint64_t upper_threshold : 6; + uint64_t stop_error : 1; + uint64_t command_complete : 1; + uint64_t data_request : 1; + uint64_t nack_received_error : 1; + uint64_t arbitration_lost_error : 1; + uint64_t back_end_access_error : 1; + uint64_t back_end_overrun_error : 1; + uint64_t lbus_parity_error : 1; + uint64_t invalid_command : 1; +#endif // _BIG_ENDIAN + } fields; +} i2cengine_status_t; + + + +typedef union i2cengine_extended_status { + + 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 table_base_addr : 32; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t table_base_addr : 32; +#endif // _BIG_ENDIAN + } fields; +} i2cengine_extended_status_t; + + + +typedef union i2cengine_residual_front_end_back_end_length { + + 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 residual_front_end_length : 16; + uint64_t residual_back_end_length : 16; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t residual_back_end_length : 16; + uint64_t residual_front_end_length : 16; +#endif // _BIG_ENDIAN + } fields; +} i2cengine_residual_front_end_back_end_length_t; + + + +typedef union i2cengine_immediate_reset_s_scl { + + 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 residual_front_end_length : 16; + uint64_t residual_back_end_length : 16; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t residual_back_end_length : 16; + uint64_t residual_front_end_length : 16; +#endif // _BIG_ENDIAN + } fields; +} i2cengine_immediate_reset_s_scl_t; + + + +typedef union i2cengine_immediate_set_s_sda { + + 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 residual_front_end_length : 16; + uint64_t residual_back_end_length : 16; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t residual_back_end_length : 16; + uint64_t residual_front_end_length : 16; +#endif // _BIG_ENDIAN + } fields; +} i2cengine_immediate_set_s_sda_t; + + + +typedef union i2cengine_immediate_reset_s_sda { + + 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 field : 1; + uint64_t _reserved0 : 63; +#else + uint64_t _reserved0 : 63; + uint64_t field : 1; +#endif // _BIG_ENDIAN + } fields; +} i2cengine_immediate_reset_s_sda_t; + + + +typedef union i2cengine_fifo_word { + + 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 data : 32; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t data : 32; +#endif // _BIG_ENDIAN + } fields; +} i2cengine_fifo_word_t; + + +#endif // __ASSEMBLER__ +#endif // __I2CENGINE_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/i2cengine_register_addresses.h b/src/ssx/pgp/registers/i2cengine_register_addresses.h new file mode 100644 index 0000000..bbe9104 --- /dev/null +++ b/src/ssx/pgp/registers/i2cengine_register_addresses.h @@ -0,0 +1,33 @@ +#ifndef __I2CENGINE_REGISTER_ADDRESSES_H__ +#define __I2CENGINE_REGISTER_ADDRESSES_H__ + +// $Id: i2cengine_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ + +/// \file i2cengine_register_addresses.h +/// \brief Symbolic addresses for the I2CENGINE unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define I2CENGINE_PIB_BASE 0x00000000 +#define I2CENGINE_FAST_CONTROL 0x00000000 +#define I2CENGINE_FAST_RESET 0x00000001 +#define I2CENGINE_FAST_STATUS 0x00000002 +#define I2CENGINE_FAST_DATA 0x00000003 +#define I2CENGINE_FIFO_BYTE 0x00000004 +#define I2CENGINE_COMMAND 0x00000005 +#define I2CENGINE_MODE 0x00000006 +#define I2CENGINE_WATERMARK 0x00000007 +#define I2CENGINE_INTERRUPT_MASK 0x00000008 +#define I2CENGINE_INTERRUPT_CONDITION 0x00000009 +#define I2CENGINE_INTERRUPTS 0x0000000a +#define I2CENGINE_STATUS 0x0000000b +#define I2CENGINE_EXTENDED_STATUS 0x0000000c +#define I2CENGINE_RESIDUAL_FRONT_END_BACK_END_LENGTH 0x0000000d +#define I2CENGINE_IMMEDIATE_RESET_S_SCL 0x0000000f +#define I2CENGINE_IMMEDIATE_SET_S_SDA 0x00000010 +#define I2CENGINE_IMMEDIATE_RESET_S_SDA 0x00000011 +#define I2CENGINE_FIFO_WORD 0x00000012 + +#endif // __I2CENGINE_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/icp_firmware_registers.h b/src/ssx/pgp/registers/icp_firmware_registers.h new file mode 100755 index 0000000..4e17a68 --- /dev/null +++ b/src/ssx/pgp/registers/icp_firmware_registers.h @@ -0,0 +1,189 @@ +#ifndef __ICP_FIRMWARE_REGISTERS_H__ +#define __ICP_FIRMWARE_REGISTERS_H__ + +// $Id: icp_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/icp_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file icp_firmware_registers.h +/// \brief C register structs for the ICP unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union icp_bar { + + 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 icp_bar : 30; + uint64_t icp_bar_en : 1; + uint64_t _reserved0 : 33; +#else + uint64_t _reserved0 : 33; + uint64_t icp_bar_en : 1; + uint64_t icp_bar : 30; +#endif // _BIG_ENDIAN + } fields; +} icp_bar_t; + +#endif // __ASSEMBLER__ +#define ICP_BAR_ICP_BAR_MASK SIXTYFOUR_BIT_CONSTANT(0xfffffffc00000000) +#define ICP_BAR_ICP_BAR_EN SIXTYFOUR_BIT_CONSTANT(0x0000000200000000) +#ifndef __ASSEMBLER__ + + +typedef union icp_mode0 { + + 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 priority : 8; + uint64_t reserved0 : 1; + uint64_t scope_initial : 3; + uint64_t reserved1 : 1; + uint64_t no_hang2status : 1; + uint64_t oper_disable_hang : 1; + uint64_t oper_hang_div : 5; + uint64_t reserved2 : 2; + uint64_t data_disable_hang : 1; + uint64_t data_hang_div : 5; + uint64_t backoff_disable : 1; + uint64_t fwd_que_fwd_conv_disable : 1; + uint64_t disa_wait4cresp_mode4ris : 1; + uint64_t disa_auto_no_retry4ris : 1; + uint64_t disa_retry_mode4ris : 1; + uint64_t hang_on_addr_error : 1; + uint64_t eoi_correction : 2; + uint64_t max_load_count : 4; + uint64_t max_store_count : 4; + uint64_t reserved3 : 3; + uint64_t enable_inject : 1; + uint64_t _reserved0 : 16; +#else + uint64_t _reserved0 : 16; + uint64_t enable_inject : 1; + uint64_t reserved3 : 3; + uint64_t max_store_count : 4; + uint64_t max_load_count : 4; + uint64_t eoi_correction : 2; + uint64_t hang_on_addr_error : 1; + uint64_t disa_retry_mode4ris : 1; + uint64_t disa_auto_no_retry4ris : 1; + uint64_t disa_wait4cresp_mode4ris : 1; + uint64_t fwd_que_fwd_conv_disable : 1; + uint64_t backoff_disable : 1; + uint64_t data_hang_div : 5; + uint64_t data_disable_hang : 1; + uint64_t reserved2 : 2; + uint64_t oper_hang_div : 5; + uint64_t oper_disable_hang : 1; + uint64_t no_hang2status : 1; + uint64_t reserved1 : 1; + uint64_t scope_initial : 3; + uint64_t reserved0 : 1; + uint64_t priority : 8; +#endif // _BIG_ENDIAN + } fields; +} icp_mode0_t; + +#endif // __ASSEMBLER__ +#define ICP_MODE0_PRIORITY_MASK SIXTYFOUR_BIT_CONSTANT(0xff00000000000000) +#define ICP_MODE0_SCOPE_INITIAL_MASK SIXTYFOUR_BIT_CONSTANT(0x0070000000000000) +#define ICP_MODE0_NO_HANG2STATUS SIXTYFOUR_BIT_CONSTANT(0x0004000000000000) +#define ICP_MODE0_OPER_DISABLE_HANG SIXTYFOUR_BIT_CONSTANT(0x0002000000000000) +#define ICP_MODE0_OPER_HANG_DIV_MASK SIXTYFOUR_BIT_CONSTANT(0x0001f00000000000) +#define ICP_MODE0_DATA_DISABLE_HANG SIXTYFOUR_BIT_CONSTANT(0x0000020000000000) +#define ICP_MODE0_DATA_HANG_DIV_MASK SIXTYFOUR_BIT_CONSTANT(0x000001f000000000) +#define ICP_MODE0_BACKOFF_DISABLE SIXTYFOUR_BIT_CONSTANT(0x0000000800000000) +#define ICP_MODE0_FWD_QUE_FWD_CONV_DISABLE SIXTYFOUR_BIT_CONSTANT(0x0000000400000000) +#define ICP_MODE0_DISA_WAIT4CRESP_MODE4RIS SIXTYFOUR_BIT_CONSTANT(0x0000000200000000) +#define ICP_MODE0_DISA_AUTO_NO_RETRY4RIS SIXTYFOUR_BIT_CONSTANT(0x0000000100000000) +#define ICP_MODE0_DISA_RETRY_MODE4RIS SIXTYFOUR_BIT_CONSTANT(0x0000000080000000) +#define ICP_MODE0_HANG_ON_ADDR_ERROR SIXTYFOUR_BIT_CONSTANT(0x0000000040000000) +#define ICP_MODE0_EOI_CORRECTION_MASK SIXTYFOUR_BIT_CONSTANT(0x0000000030000000) +#define ICP_MODE0_MAX_LOAD_COUNT_MASK SIXTYFOUR_BIT_CONSTANT(0x000000000f000000) +#define ICP_MODE0_MAX_STORE_COUNT_MASK SIXTYFOUR_BIT_CONSTANT(0x0000000000f00000) +#define ICP_MODE0_ENABLE_INJECT SIXTYFOUR_BIT_CONSTANT(0x0000000000010000) +#ifndef __ASSEMBLER__ + + +typedef union icp_iir { + + 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 inject_target_core : 16; + uint64_t inject_target_thread : 8; + uint64_t reserved0 : 8; + uint64_t inject_level : 4; + uint64_t reserved1 : 4; + uint64_t inject_priority : 8; + uint64_t _reserved0 : 16; +#else + uint64_t _reserved0 : 16; + uint64_t inject_priority : 8; + uint64_t reserved1 : 4; + uint64_t inject_level : 4; + uint64_t reserved0 : 8; + uint64_t inject_target_thread : 8; + uint64_t inject_target_core : 16; +#endif // _BIG_ENDIAN + } fields; +} icp_iir_t; + +#endif // __ASSEMBLER__ +#define ICP_IIR_INJECT_TARGET_CORE_MASK SIXTYFOUR_BIT_CONSTANT(0xffff000000000000) +#define ICP_IIR_INJECT_TARGET_THREAD_MASK SIXTYFOUR_BIT_CONSTANT(0x0000ff0000000000) +#define ICP_IIR_INJECT_LEVEL_MASK SIXTYFOUR_BIT_CONSTANT(0x00000000f0000000) +#define ICP_IIR_INJECT_PRIORITY_MASK SIXTYFOUR_BIT_CONSTANT(0x0000000000ff0000) +#ifndef __ASSEMBLER__ + +#endif // __ASSEMBLER__ +#endif // __ICP_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/icp_register_addresses.h b/src/ssx/pgp/registers/icp_register_addresses.h new file mode 100755 index 0000000..7cb8350 --- /dev/null +++ b/src/ssx/pgp/registers/icp_register_addresses.h @@ -0,0 +1,24 @@ +#ifndef __ICP_REGISTER_ADDRESSES_H__ +#define __ICP_REGISTER_ADDRESSES_H__ + +// $Id: icp_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/icp_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file icp_register_addresses.h +/// \brief Symbolic addresses for the ICP unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define ICP_PIB_BASE 0x020109c0 +#define ICP_BAR 0x020109ca +#define ICP_MODE0 0x020109cb +#define ICP_IIR 0x020109cc + +#endif // __ICP_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/mcs_firmware_registers.h b/src/ssx/pgp/registers/mcs_firmware_registers.h new file mode 100755 index 0000000..b71b888 --- /dev/null +++ b/src/ssx/pgp/registers/mcs_firmware_registers.h @@ -0,0 +1,161 @@ +#ifndef __MCS_FIRMWARE_REGISTERS_H__ +#define __MCS_FIRMWARE_REGISTERS_H__ + +// $Id: mcs_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/mcs_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file mcs_firmware_registers.h +/// \brief C register structs for the MCS unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union mcfgpr { + + 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 mcfgprq_valid : 1; + uint64_t reserved0 : 5; + uint64_t mcfgprq_base_address : 14; + uint64_t _reserved0 : 44; +#else + uint64_t _reserved0 : 44; + uint64_t mcfgprq_base_address : 14; + uint64_t reserved0 : 5; + uint64_t mcfgprq_valid : 1; +#endif // _BIG_ENDIAN + } fields; +} mcfgpr_t; + +#endif // __ASSEMBLER__ +#define MCFGPR_MCFGPRQ_VALID SIXTYFOUR_BIT_CONSTANT(0x8000000000000000) +#define MCFGPR_MCFGPRQ_BASE_ADDRESS_MASK SIXTYFOUR_BIT_CONSTANT(0x03fff00000000000) +#ifndef __ASSEMBLER__ + + +typedef union mcsmode0 { + + 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 enable_cmd_byp_stutter : 1; + uint64_t reserved1 : 1; + uint64_t enable_ns_rd_ao_sfu_for_dcbz : 1; + uint64_t enable_centaur_local_checkstop_command : 1; + uint64_t l3_prefetch_retry_threshold : 4; + uint64_t number_of_cl_entries_reserved_for_read : 4; + uint64_t number_of_cl_entries_reserved_for_mirrored_ops : 4; + uint64_t number_of_cl_entries_reserved_for_writes : 4; + uint64_t number_of_cl_entries_reserved_for_cp_writes : 4; + uint64_t number_of_cl_entries_reserved_for_cp_ig : 4; + uint64_t number_of_cl_entries_reserved_for_htm_ops : 4; + uint64_t number_of_cl_entries_reserved_for_ha_assist : 4; + uint64_t mcfgrp_19_is_ho_bit : 1; + uint64_t cl_channel_timeout_forces_channel_fail : 1; + uint64_t enable_fault_line_for_global_checkstop : 1; + uint64_t reserved39 : 5; + uint64_t address_collision_modes : 9; + uint64_t include_cp_ig_in_cp_write_fullness_group : 1; + uint64_t enable_dmawr_cmd_bit : 1; + uint64_t enable_read_lsfr_data : 1; + uint64_t force_channel_fail : 1; + uint64_t disable_read_crc_ecc_bypass_taken : 1; + uint64_t disable_cl_ao_queueus : 1; + uint64_t address_select_lfsr_value : 2; + uint64_t enable_centaur_sync : 1; + uint64_t write_data_buffer_ecc_check_disable : 1; + uint64_t write_data_buffer_ecc_correct_disable : 1; +#else + uint64_t write_data_buffer_ecc_correct_disable : 1; + uint64_t write_data_buffer_ecc_check_disable : 1; + uint64_t enable_centaur_sync : 1; + uint64_t address_select_lfsr_value : 2; + uint64_t disable_cl_ao_queueus : 1; + uint64_t disable_read_crc_ecc_bypass_taken : 1; + uint64_t force_channel_fail : 1; + uint64_t enable_read_lsfr_data : 1; + uint64_t enable_dmawr_cmd_bit : 1; + uint64_t include_cp_ig_in_cp_write_fullness_group : 1; + uint64_t address_collision_modes : 9; + uint64_t reserved39 : 5; + uint64_t enable_fault_line_for_global_checkstop : 1; + uint64_t cl_channel_timeout_forces_channel_fail : 1; + uint64_t mcfgrp_19_is_ho_bit : 1; + uint64_t number_of_cl_entries_reserved_for_ha_assist : 4; + uint64_t number_of_cl_entries_reserved_for_htm_ops : 4; + uint64_t number_of_cl_entries_reserved_for_cp_ig : 4; + uint64_t number_of_cl_entries_reserved_for_cp_writes : 4; + uint64_t number_of_cl_entries_reserved_for_writes : 4; + uint64_t number_of_cl_entries_reserved_for_mirrored_ops : 4; + uint64_t number_of_cl_entries_reserved_for_read : 4; + uint64_t l3_prefetch_retry_threshold : 4; + uint64_t enable_centaur_local_checkstop_command : 1; + uint64_t enable_ns_rd_ao_sfu_for_dcbz : 1; + uint64_t reserved1 : 1; + uint64_t enable_cmd_byp_stutter : 1; +#endif // _BIG_ENDIAN + } fields; +} mcsmode0_t; + +#endif // __ASSEMBLER__ +#define MCSMODE0_ENABLE_CMD_BYP_STUTTER SIXTYFOUR_BIT_CONSTANT(0x8000000000000000) +#define MCSMODE0_ENABLE_NS_RD_AO_SFU_FOR_DCBZ SIXTYFOUR_BIT_CONSTANT(0x2000000000000000) +#define MCSMODE0_ENABLE_CENTAUR_LOCAL_CHECKSTOP_COMMAND SIXTYFOUR_BIT_CONSTANT(0x1000000000000000) +#define MCSMODE0_L3_PREFETCH_RETRY_THRESHOLD_MASK SIXTYFOUR_BIT_CONSTANT(0x0f00000000000000) +#define MCSMODE0_MCFGRP_19_IS_HO_BIT SIXTYFOUR_BIT_CONSTANT(0x0000000008000000) +#define MCSMODE0_CL_CHANNEL_TIMEOUT_FORCES_CHANNEL_FAIL SIXTYFOUR_BIT_CONSTANT(0x0000000004000000) +#define MCSMODE0_ENABLE_FAULT_LINE_FOR_GLOBAL_CHECKSTOP SIXTYFOUR_BIT_CONSTANT(0x0000000002000000) +#define MCSMODE0_ADDRESS_COLLISION_MODES_MASK SIXTYFOUR_BIT_CONSTANT(0x00000000000ff800) +#define MCSMODE0_INCLUDE_CP_IG_IN_CP_WRITE_FULLNESS_GROUP SIXTYFOUR_BIT_CONSTANT(0x0000000000000400) +#define MCSMODE0_ENABLE_DMAWR_CMD_BIT SIXTYFOUR_BIT_CONSTANT(0x0000000000000200) +#define MCSMODE0_ENABLE_READ_LSFR_DATA SIXTYFOUR_BIT_CONSTANT(0x0000000000000100) +#define MCSMODE0_FORCE_CHANNEL_FAIL SIXTYFOUR_BIT_CONSTANT(0x0000000000000080) +#define MCSMODE0_DISABLE_READ_CRC_ECC_BYPASS_TAKEN SIXTYFOUR_BIT_CONSTANT(0x0000000000000040) +#define MCSMODE0_DISABLE_CL_AO_QUEUEUS SIXTYFOUR_BIT_CONSTANT(0x0000000000000020) +#define MCSMODE0_ADDRESS_SELECT_LFSR_VALUE_MASK SIXTYFOUR_BIT_CONSTANT(0x0000000000000018) +#define MCSMODE0_ENABLE_CENTAUR_SYNC SIXTYFOUR_BIT_CONSTANT(0x0000000000000004) +#define MCSMODE0_WRITE_DATA_BUFFER_ECC_CHECK_DISABLE SIXTYFOUR_BIT_CONSTANT(0x0000000000000002) +#define MCSMODE0_WRITE_DATA_BUFFER_ECC_CORRECT_DISABLE SIXTYFOUR_BIT_CONSTANT(0x0000000000000001) +#ifndef __ASSEMBLER__ + +#endif // __ASSEMBLER__ +#endif // __MCS_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/mcs_register_addresses.h b/src/ssx/pgp/registers/mcs_register_addresses.h new file mode 100755 index 0000000..bc7f95c --- /dev/null +++ b/src/ssx/pgp/registers/mcs_register_addresses.h @@ -0,0 +1,46 @@ +#ifndef __MCS_REGISTER_ADDRESSES_H__ +#define __MCS_REGISTER_ADDRESSES_H__ + +// $Id: mcs_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/mcs_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file mcs_register_addresses.h +/// \brief Symbolic addresses for the MCS unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define MCS0_PIB_BASE 0x02011800 +#define MCS1_PIB_BASE 0x02011880 +#define MCS2_PIB_BASE 0x02011900 +#define MCS3_PIB_BASE 0x02011980 +#define MCS4_PIB_BASE 0x02011C00 +#define MCS5_PIB_BASE 0x02011C80 +#define MCS6_PIB_BASE 0x02011D00 +#define MCS7_PIB_BASE 0x02011D80 +#define MCFGPR_OFFSET 0x00000002 +#define MCS0_MCFGPR 0x02011802 +#define MCS1_MCFGPR 0x02011882 +#define MCS2_MCFGPR 0x02011902 +#define MCS3_MCFGPR 0x02011982 +#define MCS4_MCFGPR 0x02011c02 +#define MCS5_MCFGPR 0x02011c82 +#define MCS6_MCFGPR 0x02011d02 +#define MCS7_MCFGPR 0x02011d82 +#define MCSMODE0_OFFSET 0x00000007 +#define MCS0_MCSMODE0 0x02011807 +#define MCS1_MCSMODE0 0x02011887 +#define MCS2_MCSMODE0 0x02011907 +#define MCS3_MCSMODE0 0x02011987 +#define MCS4_MCSMODE0 0x02011c07 +#define MCS5_MCSMODE0 0x02011c87 +#define MCS6_MCSMODE0 0x02011d07 +#define MCS7_MCSMODE0 0x02011d87 + +#endif // __MCS_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/ocb_firmware_registers.h b/src/ssx/pgp/registers/ocb_firmware_registers.h new file mode 100755 index 0000000..4a4ddb2 --- /dev/null +++ b/src/ssx/pgp/registers/ocb_firmware_registers.h @@ -0,0 +1,2668 @@ +#ifndef __OCB_FIRMWARE_REGISTERS_H__ +#define __OCB_FIRMWARE_REGISTERS_H__ + +// $Id: ocb_firmware_registers.h,v 1.2 2014/03/14 15:33:03 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/ocb_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2014 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ocb_firmware_registers.h +/// \brief C register structs for the OCB unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union ocb_oitr0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t value : 32; +#else + uint32_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_oitr0_t; + + + +typedef union ocb_oiepr0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t value : 32; +#else + uint32_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_oiepr0_t; + + + +typedef union ocb_ocir0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t value : 32; +#else + uint32_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocir0_t; + + + +typedef union ocb_onisr0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t value : 32; +#else + uint32_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_onisr0_t; + + + +typedef union ocb_ouder0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t value : 32; +#else + uint32_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_ouder0_t; + + + +typedef union ocb_ocisr0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t value : 32; +#else + uint32_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocisr0_t; + + + +typedef union ocb_odher0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t dbg_halt_en : 32; +#else + uint32_t dbg_halt_en : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_odher0_t; + + + +typedef union ocb_oisr0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t debugger : 1; + uint32_t trace_trigger : 1; + uint32_t reserved_2 : 1; + uint32_t pba_error : 1; + uint32_t srt_error : 1; + uint32_t pore_sw_error : 1; + uint32_t pore_gpe0_fatal_error : 1; + uint32_t pore_gpe1_fatal_error : 1; + uint32_t pore_sbe_fatal_error : 1; + uint32_t pmc_error : 1; + uint32_t ocb_error : 1; + uint32_t spipss_error : 1; + uint32_t check_stop : 1; + uint32_t pmc_malf_alert : 1; + uint32_t adu_malf_alert : 1; + uint32_t external_trap : 1; + uint32_t occ_timer0 : 1; + uint32_t occ_timer1 : 1; + uint32_t pore_gpe0_error : 1; + uint32_t pore_gpe1_error : 1; + uint32_t pore_sbe_error : 1; + uint32_t pmc_interchip_msg_recv : 1; + uint32_t reserved_22 : 1; + uint32_t pore_gpe0_complete : 1; + uint32_t pore_gpe1_complete : 1; + uint32_t adcfsm_ongoing : 1; + uint32_t reserved_26 : 1; + uint32_t pba_occ_push0 : 1; + uint32_t pba_occ_push1 : 1; + uint32_t pba_bcde_attn : 1; + uint32_t pba_bcue_attn : 1; + uint32_t reserved_31 : 1; +#else + uint32_t reserved_31 : 1; + uint32_t pba_bcue_attn : 1; + uint32_t pba_bcde_attn : 1; + uint32_t pba_occ_push1 : 1; + uint32_t pba_occ_push0 : 1; + uint32_t reserved_26 : 1; + uint32_t adcfsm_ongoing : 1; + uint32_t pore_gpe1_complete : 1; + uint32_t pore_gpe0_complete : 1; + uint32_t reserved_22 : 1; + uint32_t pmc_interchip_msg_recv : 1; + uint32_t pore_sbe_error : 1; + uint32_t pore_gpe1_error : 1; + uint32_t pore_gpe0_error : 1; + uint32_t occ_timer1 : 1; + uint32_t occ_timer0 : 1; + uint32_t external_trap : 1; + uint32_t adu_malf_alert : 1; + uint32_t pmc_malf_alert : 1; + uint32_t check_stop : 1; + uint32_t spipss_error : 1; + uint32_t ocb_error : 1; + uint32_t pmc_error : 1; + uint32_t pore_sbe_fatal_error : 1; + uint32_t pore_gpe1_fatal_error : 1; + uint32_t pore_gpe0_fatal_error : 1; + uint32_t pore_sw_error : 1; + uint32_t srt_error : 1; + uint32_t pba_error : 1; + uint32_t reserved_2 : 1; + uint32_t trace_trigger : 1; + uint32_t debugger : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_oisr0_t; + + + +typedef union ocb_oisr0_and { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t debugger : 1; + uint32_t trace_trigger : 1; + uint32_t reserved_2 : 1; + uint32_t pba_error : 1; + uint32_t srt_error : 1; + uint32_t pore_sw_error : 1; + uint32_t pore_gpe0_fatal_error : 1; + uint32_t pore_gpe1_fatal_error : 1; + uint32_t pore_sbe_fatal_error : 1; + uint32_t pmc_error : 1; + uint32_t ocb_error : 1; + uint32_t spipss_error : 1; + uint32_t check_stop : 1; + uint32_t pmc_malf_alert : 1; + uint32_t adu_malf_alert : 1; + uint32_t external_trap : 1; + uint32_t occ_timer0 : 1; + uint32_t occ_timer1 : 1; + uint32_t pore_gpe0_error : 1; + uint32_t pore_gpe1_error : 1; + uint32_t pore_sbe_error : 1; + uint32_t pmc_interchip_msg_recv : 1; + uint32_t reserved_22 : 1; + uint32_t pore_gpe0_complete : 1; + uint32_t pore_gpe1_complete : 1; + uint32_t adcfsm_ongoing : 1; + uint32_t reserved_26 : 1; + uint32_t pba_occ_push0 : 1; + uint32_t pba_occ_push1 : 1; + uint32_t pba_bcde_attn : 1; + uint32_t pba_bcue_attn : 1; + uint32_t reserved_31 : 1; +#else + uint32_t reserved_31 : 1; + uint32_t pba_bcue_attn : 1; + uint32_t pba_bcde_attn : 1; + uint32_t pba_occ_push1 : 1; + uint32_t pba_occ_push0 : 1; + uint32_t reserved_26 : 1; + uint32_t adcfsm_ongoing : 1; + uint32_t pore_gpe1_complete : 1; + uint32_t pore_gpe0_complete : 1; + uint32_t reserved_22 : 1; + uint32_t pmc_interchip_msg_recv : 1; + uint32_t pore_sbe_error : 1; + uint32_t pore_gpe1_error : 1; + uint32_t pore_gpe0_error : 1; + uint32_t occ_timer1 : 1; + uint32_t occ_timer0 : 1; + uint32_t external_trap : 1; + uint32_t adu_malf_alert : 1; + uint32_t pmc_malf_alert : 1; + uint32_t check_stop : 1; + uint32_t spipss_error : 1; + uint32_t ocb_error : 1; + uint32_t pmc_error : 1; + uint32_t pore_sbe_fatal_error : 1; + uint32_t pore_gpe1_fatal_error : 1; + uint32_t pore_gpe0_fatal_error : 1; + uint32_t pore_sw_error : 1; + uint32_t srt_error : 1; + uint32_t pba_error : 1; + uint32_t reserved_2 : 1; + uint32_t trace_trigger : 1; + uint32_t debugger : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_oisr0_and_t; + + + +typedef union ocb_oisr0_or { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t debugger : 1; + uint32_t trace_trigger : 1; + uint32_t reserved_2 : 1; + uint32_t pba_error : 1; + uint32_t srt_error : 1; + uint32_t pore_sw_error : 1; + uint32_t pore_gpe0_fatal_error : 1; + uint32_t pore_gpe1_fatal_error : 1; + uint32_t pore_sbe_fatal_error : 1; + uint32_t pmc_error : 1; + uint32_t ocb_error : 1; + uint32_t spipss_error : 1; + uint32_t check_stop : 1; + uint32_t pmc_malf_alert : 1; + uint32_t adu_malf_alert : 1; + uint32_t external_trap : 1; + uint32_t occ_timer0 : 1; + uint32_t occ_timer1 : 1; + uint32_t pore_gpe0_error : 1; + uint32_t pore_gpe1_error : 1; + uint32_t pore_sbe_error : 1; + uint32_t pmc_interchip_msg_recv : 1; + uint32_t reserved_22 : 1; + uint32_t pore_gpe0_complete : 1; + uint32_t pore_gpe1_complete : 1; + uint32_t adcfsm_ongoing : 1; + uint32_t reserved_26 : 1; + uint32_t pba_occ_push0 : 1; + uint32_t pba_occ_push1 : 1; + uint32_t pba_bcde_attn : 1; + uint32_t pba_bcue_attn : 1; + uint32_t reserved_31 : 1; +#else + uint32_t reserved_31 : 1; + uint32_t pba_bcue_attn : 1; + uint32_t pba_bcde_attn : 1; + uint32_t pba_occ_push1 : 1; + uint32_t pba_occ_push0 : 1; + uint32_t reserved_26 : 1; + uint32_t adcfsm_ongoing : 1; + uint32_t pore_gpe1_complete : 1; + uint32_t pore_gpe0_complete : 1; + uint32_t reserved_22 : 1; + uint32_t pmc_interchip_msg_recv : 1; + uint32_t pore_sbe_error : 1; + uint32_t pore_gpe1_error : 1; + uint32_t pore_gpe0_error : 1; + uint32_t occ_timer1 : 1; + uint32_t occ_timer0 : 1; + uint32_t external_trap : 1; + uint32_t adu_malf_alert : 1; + uint32_t pmc_malf_alert : 1; + uint32_t check_stop : 1; + uint32_t spipss_error : 1; + uint32_t ocb_error : 1; + uint32_t pmc_error : 1; + uint32_t pore_sbe_fatal_error : 1; + uint32_t pore_gpe1_fatal_error : 1; + uint32_t pore_gpe0_fatal_error : 1; + uint32_t pore_sw_error : 1; + uint32_t srt_error : 1; + uint32_t pba_error : 1; + uint32_t reserved_2 : 1; + uint32_t trace_trigger : 1; + uint32_t debugger : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_oisr0_or_t; + + + +typedef union ocb_oimr0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t debugger : 1; + uint32_t trace_trigger : 1; + uint32_t reserved_2 : 1; + uint32_t pba_error : 1; + uint32_t srt_error : 1; + uint32_t pore_sw_error : 1; + uint32_t pore_gpe0_fatal_error : 1; + uint32_t pore_gpe1_fatal_error : 1; + uint32_t pore_sbe_fatal_error : 1; + uint32_t pmc_error : 1; + uint32_t ocb_error : 1; + uint32_t spipss_error : 1; + uint32_t check_stop : 1; + uint32_t pmc_malf_alert : 1; + uint32_t adu_malf_alert : 1; + uint32_t external_trap : 1; + uint32_t occ_timer0 : 1; + uint32_t occ_timer1 : 1; + uint32_t pore_gpe0_error : 1; + uint32_t pore_gpe1_error : 1; + uint32_t pore_sbe_error : 1; + uint32_t pmc_interchip_msg_recv : 1; + uint32_t reserved_22 : 1; + uint32_t pore_gpe0_complete : 1; + uint32_t pore_gpe1_complete : 1; + uint32_t adcfsm_ongoing : 1; + uint32_t reserved_26 : 1; + uint32_t pba_occ_push0 : 1; + uint32_t pba_occ_push1 : 1; + uint32_t pba_bcde_attn : 1; + uint32_t pba_bcue_attn : 1; + uint32_t reserved_31 : 1; +#else + uint32_t reserved_31 : 1; + uint32_t pba_bcue_attn : 1; + uint32_t pba_bcde_attn : 1; + uint32_t pba_occ_push1 : 1; + uint32_t pba_occ_push0 : 1; + uint32_t reserved_26 : 1; + uint32_t adcfsm_ongoing : 1; + uint32_t pore_gpe1_complete : 1; + uint32_t pore_gpe0_complete : 1; + uint32_t reserved_22 : 1; + uint32_t pmc_interchip_msg_recv : 1; + uint32_t pore_sbe_error : 1; + uint32_t pore_gpe1_error : 1; + uint32_t pore_gpe0_error : 1; + uint32_t occ_timer1 : 1; + uint32_t occ_timer0 : 1; + uint32_t external_trap : 1; + uint32_t adu_malf_alert : 1; + uint32_t pmc_malf_alert : 1; + uint32_t check_stop : 1; + uint32_t spipss_error : 1; + uint32_t ocb_error : 1; + uint32_t pmc_error : 1; + uint32_t pore_sbe_fatal_error : 1; + uint32_t pore_gpe1_fatal_error : 1; + uint32_t pore_gpe0_fatal_error : 1; + uint32_t pore_sw_error : 1; + uint32_t srt_error : 1; + uint32_t pba_error : 1; + uint32_t reserved_2 : 1; + uint32_t trace_trigger : 1; + uint32_t debugger : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_oimr0_t; + + + +typedef union ocb_oimr0_and { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t debugger : 1; + uint32_t trace_trigger : 1; + uint32_t reserved_2 : 1; + uint32_t pba_error : 1; + uint32_t srt_error : 1; + uint32_t pore_sw_error : 1; + uint32_t pore_gpe0_fatal_error : 1; + uint32_t pore_gpe1_fatal_error : 1; + uint32_t pore_sbe_fatal_error : 1; + uint32_t pmc_error : 1; + uint32_t ocb_error : 1; + uint32_t spipss_error : 1; + uint32_t check_stop : 1; + uint32_t pmc_malf_alert : 1; + uint32_t adu_malf_alert : 1; + uint32_t external_trap : 1; + uint32_t occ_timer0 : 1; + uint32_t occ_timer1 : 1; + uint32_t pore_gpe0_error : 1; + uint32_t pore_gpe1_error : 1; + uint32_t pore_sbe_error : 1; + uint32_t pmc_interchip_msg_recv : 1; + uint32_t reserved_22 : 1; + uint32_t pore_gpe0_complete : 1; + uint32_t pore_gpe1_complete : 1; + uint32_t adcfsm_ongoing : 1; + uint32_t reserved_26 : 1; + uint32_t pba_occ_push0 : 1; + uint32_t pba_occ_push1 : 1; + uint32_t pba_bcde_attn : 1; + uint32_t pba_bcue_attn : 1; + uint32_t reserved_31 : 1; +#else + uint32_t reserved_31 : 1; + uint32_t pba_bcue_attn : 1; + uint32_t pba_bcde_attn : 1; + uint32_t pba_occ_push1 : 1; + uint32_t pba_occ_push0 : 1; + uint32_t reserved_26 : 1; + uint32_t adcfsm_ongoing : 1; + uint32_t pore_gpe1_complete : 1; + uint32_t pore_gpe0_complete : 1; + uint32_t reserved_22 : 1; + uint32_t pmc_interchip_msg_recv : 1; + uint32_t pore_sbe_error : 1; + uint32_t pore_gpe1_error : 1; + uint32_t pore_gpe0_error : 1; + uint32_t occ_timer1 : 1; + uint32_t occ_timer0 : 1; + uint32_t external_trap : 1; + uint32_t adu_malf_alert : 1; + uint32_t pmc_malf_alert : 1; + uint32_t check_stop : 1; + uint32_t spipss_error : 1; + uint32_t ocb_error : 1; + uint32_t pmc_error : 1; + uint32_t pore_sbe_fatal_error : 1; + uint32_t pore_gpe1_fatal_error : 1; + uint32_t pore_gpe0_fatal_error : 1; + uint32_t pore_sw_error : 1; + uint32_t srt_error : 1; + uint32_t pba_error : 1; + uint32_t reserved_2 : 1; + uint32_t trace_trigger : 1; + uint32_t debugger : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_oimr0_and_t; + + + +typedef union ocb_oimr0_or { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t debugger : 1; + uint32_t trace_trigger : 1; + uint32_t reserved_2 : 1; + uint32_t pba_error : 1; + uint32_t srt_error : 1; + uint32_t pore_sw_error : 1; + uint32_t pore_gpe0_fatal_error : 1; + uint32_t pore_gpe1_fatal_error : 1; + uint32_t pore_sbe_fatal_error : 1; + uint32_t pmc_error : 1; + uint32_t ocb_error : 1; + uint32_t spipss_error : 1; + uint32_t check_stop : 1; + uint32_t pmc_malf_alert : 1; + uint32_t adu_malf_alert : 1; + uint32_t external_trap : 1; + uint32_t occ_timer0 : 1; + uint32_t occ_timer1 : 1; + uint32_t pore_gpe0_error : 1; + uint32_t pore_gpe1_error : 1; + uint32_t pore_sbe_error : 1; + uint32_t pmc_interchip_msg_recv : 1; + uint32_t reserved_22 : 1; + uint32_t pore_gpe0_complete : 1; + uint32_t pore_gpe1_complete : 1; + uint32_t adcfsm_ongoing : 1; + uint32_t reserved_26 : 1; + uint32_t pba_occ_push0 : 1; + uint32_t pba_occ_push1 : 1; + uint32_t pba_bcde_attn : 1; + uint32_t pba_bcue_attn : 1; + uint32_t reserved_31 : 1; +#else + uint32_t reserved_31 : 1; + uint32_t pba_bcue_attn : 1; + uint32_t pba_bcde_attn : 1; + uint32_t pba_occ_push1 : 1; + uint32_t pba_occ_push0 : 1; + uint32_t reserved_26 : 1; + uint32_t adcfsm_ongoing : 1; + uint32_t pore_gpe1_complete : 1; + uint32_t pore_gpe0_complete : 1; + uint32_t reserved_22 : 1; + uint32_t pmc_interchip_msg_recv : 1; + uint32_t pore_sbe_error : 1; + uint32_t pore_gpe1_error : 1; + uint32_t pore_gpe0_error : 1; + uint32_t occ_timer1 : 1; + uint32_t occ_timer0 : 1; + uint32_t external_trap : 1; + uint32_t adu_malf_alert : 1; + uint32_t pmc_malf_alert : 1; + uint32_t check_stop : 1; + uint32_t spipss_error : 1; + uint32_t ocb_error : 1; + uint32_t pmc_error : 1; + uint32_t pore_sbe_fatal_error : 1; + uint32_t pore_gpe1_fatal_error : 1; + uint32_t pore_gpe0_fatal_error : 1; + uint32_t pore_sw_error : 1; + uint32_t srt_error : 1; + uint32_t pba_error : 1; + uint32_t reserved_2 : 1; + uint32_t trace_trigger : 1; + uint32_t debugger : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_oimr0_or_t; + + + +typedef union ocb_oitr1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t value : 32; +#else + uint32_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_oitr1_t; + + + +typedef union ocb_oiepr1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t value : 32; +#else + uint32_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_oiepr1_t; + + + +typedef union ocb_ocir1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t value : 32; +#else + uint32_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocir1_t; + + + +typedef union ocb_onisr1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t value : 32; +#else + uint32_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_onisr1_t; + + + +typedef union ocb_ouder1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t value : 32; +#else + uint32_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_ouder1_t; + + + +typedef union ocb_ocisr1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t value : 32; +#else + uint32_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocisr1_t; + + + +typedef union ocb_odher1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t dbg_halt_en : 32; +#else + uint32_t dbg_halt_en : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_odher1_t; + + + +typedef union ocb_oisr1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t reserved_32 : 1; + uint32_t reserved_33 : 1; + uint32_t occ_strm0_pull : 1; + uint32_t occ_strm0_push : 1; + uint32_t occ_strm1_pull : 1; + uint32_t occ_strm1_push : 1; + uint32_t occ_strm2_pull : 1; + uint32_t occ_strm2_push : 1; + uint32_t occ_strm3_pull : 1; + uint32_t occ_strm3_push : 1; + uint32_t reserved_42 : 1; + uint32_t reserved_43 : 1; + uint32_t pmc_voltage_change_ongoing : 1; + uint32_t pmc_protocol_ongoing : 1; + uint32_t pmc_sync : 1; + uint32_t pmc_pstate_change : 1; + uint32_t reserved_48 : 1; + uint32_t reserved_49 : 1; + uint32_t pmc_idle_exit : 1; + uint32_t pore_sw_complete : 1; + uint32_t pmc_idle_enter : 1; + uint32_t reserved_53 : 1; + uint32_t pmc_interchip_msg_send_ongoing : 1; + uint32_t oci2spivid_ongoing : 1; + uint32_t pmc_ocb_o2p_ongoing : 1; + uint32_t pssbridge_ongoing : 1; + uint32_t pore_sbe_complete : 1; + uint32_t ipi0 : 1; + uint32_t ipi1 : 1; + uint32_t ipi2 : 1; + uint32_t ipi3 : 1; + uint32_t reserved_63 : 1; +#else + uint32_t reserved_63 : 1; + uint32_t ipi3 : 1; + uint32_t ipi2 : 1; + uint32_t ipi1 : 1; + uint32_t ipi0 : 1; + uint32_t pore_sbe_complete : 1; + uint32_t pssbridge_ongoing : 1; + uint32_t pmc_ocb_o2p_ongoing : 1; + uint32_t oci2spivid_ongoing : 1; + uint32_t pmc_interchip_msg_send_ongoing : 1; + uint32_t reserved_53 : 1; + uint32_t pmc_idle_enter : 1; + uint32_t pore_sw_complete : 1; + uint32_t pmc_idle_exit : 1; + uint32_t reserved_49 : 1; + uint32_t reserved_48 : 1; + uint32_t pmc_pstate_change : 1; + uint32_t pmc_sync : 1; + uint32_t pmc_protocol_ongoing : 1; + uint32_t pmc_voltage_change_ongoing : 1; + uint32_t reserved_43 : 1; + uint32_t reserved_42 : 1; + uint32_t occ_strm3_push : 1; + uint32_t occ_strm3_pull : 1; + uint32_t occ_strm2_push : 1; + uint32_t occ_strm2_pull : 1; + uint32_t occ_strm1_push : 1; + uint32_t occ_strm1_pull : 1; + uint32_t occ_strm0_push : 1; + uint32_t occ_strm0_pull : 1; + uint32_t reserved_33 : 1; + uint32_t reserved_32 : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_oisr1_t; + + + +typedef union ocb_oisr1_and { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t reserved_32 : 1; + uint32_t reserved_33 : 1; + uint32_t occ_strm0_pull : 1; + uint32_t occ_strm0_push : 1; + uint32_t occ_strm1_pull : 1; + uint32_t occ_strm1_push : 1; + uint32_t occ_strm2_pull : 1; + uint32_t occ_strm2_push : 1; + uint32_t occ_strm3_pull : 1; + uint32_t occ_strm3_push : 1; + uint32_t reserved_42 : 1; + uint32_t reserved_43 : 1; + uint32_t pmc_voltage_change_ongoing : 1; + uint32_t pmc_protocol_ongoing : 1; + uint32_t pmc_sync : 1; + uint32_t pmc_pstate_change : 1; + uint32_t reserved_48 : 1; + uint32_t reserved_49 : 1; + uint32_t pmc_idle_exit : 1; + uint32_t pore_sw_complete : 1; + uint32_t pmc_idle_enter : 1; + uint32_t reserved_53 : 1; + uint32_t pmc_interchip_msg_send_ongoing : 1; + uint32_t oci2spivid_ongoing : 1; + uint32_t pmc_ocb_o2p_ongoing : 1; + uint32_t pssbridge_ongoing : 1; + uint32_t pore_sbe_complete : 1; + uint32_t ipi0 : 1; + uint32_t ipi1 : 1; + uint32_t ipi2 : 1; + uint32_t ipi3 : 1; + uint32_t reserved_63 : 1; +#else + uint32_t reserved_63 : 1; + uint32_t ipi3 : 1; + uint32_t ipi2 : 1; + uint32_t ipi1 : 1; + uint32_t ipi0 : 1; + uint32_t pore_sbe_complete : 1; + uint32_t pssbridge_ongoing : 1; + uint32_t pmc_ocb_o2p_ongoing : 1; + uint32_t oci2spivid_ongoing : 1; + uint32_t pmc_interchip_msg_send_ongoing : 1; + uint32_t reserved_53 : 1; + uint32_t pmc_idle_enter : 1; + uint32_t pore_sw_complete : 1; + uint32_t pmc_idle_exit : 1; + uint32_t reserved_49 : 1; + uint32_t reserved_48 : 1; + uint32_t pmc_pstate_change : 1; + uint32_t pmc_sync : 1; + uint32_t pmc_protocol_ongoing : 1; + uint32_t pmc_voltage_change_ongoing : 1; + uint32_t reserved_43 : 1; + uint32_t reserved_42 : 1; + uint32_t occ_strm3_push : 1; + uint32_t occ_strm3_pull : 1; + uint32_t occ_strm2_push : 1; + uint32_t occ_strm2_pull : 1; + uint32_t occ_strm1_push : 1; + uint32_t occ_strm1_pull : 1; + uint32_t occ_strm0_push : 1; + uint32_t occ_strm0_pull : 1; + uint32_t reserved_33 : 1; + uint32_t reserved_32 : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_oisr1_and_t; + + + +typedef union ocb_oisr1_or { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t reserved_32 : 1; + uint32_t reserved_33 : 1; + uint32_t occ_strm0_pull : 1; + uint32_t occ_strm0_push : 1; + uint32_t occ_strm1_pull : 1; + uint32_t occ_strm1_push : 1; + uint32_t occ_strm2_pull : 1; + uint32_t occ_strm2_push : 1; + uint32_t occ_strm3_pull : 1; + uint32_t occ_strm3_push : 1; + uint32_t reserved_42 : 1; + uint32_t reserved_43 : 1; + uint32_t pmc_voltage_change_ongoing : 1; + uint32_t pmc_protocol_ongoing : 1; + uint32_t pmc_sync : 1; + uint32_t pmc_pstate_change : 1; + uint32_t reserved_48 : 1; + uint32_t reserved_49 : 1; + uint32_t pmc_idle_exit : 1; + uint32_t pore_sw_complete : 1; + uint32_t pmc_idle_enter : 1; + uint32_t reserved_53 : 1; + uint32_t pmc_interchip_msg_send_ongoing : 1; + uint32_t oci2spivid_ongoing : 1; + uint32_t pmc_ocb_o2p_ongoing : 1; + uint32_t pssbridge_ongoing : 1; + uint32_t pore_sbe_complete : 1; + uint32_t ipi0 : 1; + uint32_t ipi1 : 1; + uint32_t ipi2 : 1; + uint32_t ipi3 : 1; + uint32_t reserved_63 : 1; +#else + uint32_t reserved_63 : 1; + uint32_t ipi3 : 1; + uint32_t ipi2 : 1; + uint32_t ipi1 : 1; + uint32_t ipi0 : 1; + uint32_t pore_sbe_complete : 1; + uint32_t pssbridge_ongoing : 1; + uint32_t pmc_ocb_o2p_ongoing : 1; + uint32_t oci2spivid_ongoing : 1; + uint32_t pmc_interchip_msg_send_ongoing : 1; + uint32_t reserved_53 : 1; + uint32_t pmc_idle_enter : 1; + uint32_t pore_sw_complete : 1; + uint32_t pmc_idle_exit : 1; + uint32_t reserved_49 : 1; + uint32_t reserved_48 : 1; + uint32_t pmc_pstate_change : 1; + uint32_t pmc_sync : 1; + uint32_t pmc_protocol_ongoing : 1; + uint32_t pmc_voltage_change_ongoing : 1; + uint32_t reserved_43 : 1; + uint32_t reserved_42 : 1; + uint32_t occ_strm3_push : 1; + uint32_t occ_strm3_pull : 1; + uint32_t occ_strm2_push : 1; + uint32_t occ_strm2_pull : 1; + uint32_t occ_strm1_push : 1; + uint32_t occ_strm1_pull : 1; + uint32_t occ_strm0_push : 1; + uint32_t occ_strm0_pull : 1; + uint32_t reserved_33 : 1; + uint32_t reserved_32 : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_oisr1_or_t; + + + +typedef union ocb_oimr1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t reserved_32 : 1; + uint32_t reserved_33 : 1; + uint32_t occ_strm0_pull : 1; + uint32_t occ_strm0_push : 1; + uint32_t occ_strm1_pull : 1; + uint32_t occ_strm1_push : 1; + uint32_t occ_strm2_pull : 1; + uint32_t occ_strm2_push : 1; + uint32_t occ_strm3_pull : 1; + uint32_t occ_strm3_push : 1; + uint32_t reserved_42 : 1; + uint32_t reserved_43 : 1; + uint32_t pmc_voltage_change_ongoing : 1; + uint32_t pmc_protocol_ongoing : 1; + uint32_t pmc_sync : 1; + uint32_t pmc_pstate_change : 1; + uint32_t reserved_48 : 1; + uint32_t reserved_49 : 1; + uint32_t pmc_idle_exit : 1; + uint32_t pore_sw_complete : 1; + uint32_t pmc_idle_enter : 1; + uint32_t reserved_53 : 1; + uint32_t pmc_interchip_msg_send_ongoing : 1; + uint32_t oci2spivid_ongoing : 1; + uint32_t pmc_ocb_o2p_ongoing : 1; + uint32_t pssbridge_ongoing : 1; + uint32_t pore_sbe_complete : 1; + uint32_t ipi0 : 1; + uint32_t ipi1 : 1; + uint32_t ipi2 : 1; + uint32_t ipi3 : 1; + uint32_t reserved_63 : 1; +#else + uint32_t reserved_63 : 1; + uint32_t ipi3 : 1; + uint32_t ipi2 : 1; + uint32_t ipi1 : 1; + uint32_t ipi0 : 1; + uint32_t pore_sbe_complete : 1; + uint32_t pssbridge_ongoing : 1; + uint32_t pmc_ocb_o2p_ongoing : 1; + uint32_t oci2spivid_ongoing : 1; + uint32_t pmc_interchip_msg_send_ongoing : 1; + uint32_t reserved_53 : 1; + uint32_t pmc_idle_enter : 1; + uint32_t pore_sw_complete : 1; + uint32_t pmc_idle_exit : 1; + uint32_t reserved_49 : 1; + uint32_t reserved_48 : 1; + uint32_t pmc_pstate_change : 1; + uint32_t pmc_sync : 1; + uint32_t pmc_protocol_ongoing : 1; + uint32_t pmc_voltage_change_ongoing : 1; + uint32_t reserved_43 : 1; + uint32_t reserved_42 : 1; + uint32_t occ_strm3_push : 1; + uint32_t occ_strm3_pull : 1; + uint32_t occ_strm2_push : 1; + uint32_t occ_strm2_pull : 1; + uint32_t occ_strm1_push : 1; + uint32_t occ_strm1_pull : 1; + uint32_t occ_strm0_push : 1; + uint32_t occ_strm0_pull : 1; + uint32_t reserved_33 : 1; + uint32_t reserved_32 : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_oimr1_t; + + + +typedef union ocb_oimr1_and { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t reserved_32 : 1; + uint32_t reserved_33 : 1; + uint32_t occ_strm0_pull : 1; + uint32_t occ_strm0_push : 1; + uint32_t occ_strm1_pull : 1; + uint32_t occ_strm1_push : 1; + uint32_t occ_strm2_pull : 1; + uint32_t occ_strm2_push : 1; + uint32_t occ_strm3_pull : 1; + uint32_t occ_strm3_push : 1; + uint32_t reserved_42 : 1; + uint32_t reserved_43 : 1; + uint32_t pmc_voltage_change_ongoing : 1; + uint32_t pmc_protocol_ongoing : 1; + uint32_t pmc_sync : 1; + uint32_t pmc_pstate_change : 1; + uint32_t reserved_48 : 1; + uint32_t reserved_49 : 1; + uint32_t pmc_idle_exit : 1; + uint32_t pore_sw_complete : 1; + uint32_t pmc_idle_enter : 1; + uint32_t reserved_53 : 1; + uint32_t pmc_interchip_msg_send_ongoing : 1; + uint32_t oci2spivid_ongoing : 1; + uint32_t pmc_ocb_o2p_ongoing : 1; + uint32_t pssbridge_ongoing : 1; + uint32_t pore_sbe_complete : 1; + uint32_t ipi0 : 1; + uint32_t ipi1 : 1; + uint32_t ipi2 : 1; + uint32_t ipi3 : 1; + uint32_t reserved_63 : 1; +#else + uint32_t reserved_63 : 1; + uint32_t ipi3 : 1; + uint32_t ipi2 : 1; + uint32_t ipi1 : 1; + uint32_t ipi0 : 1; + uint32_t pore_sbe_complete : 1; + uint32_t pssbridge_ongoing : 1; + uint32_t pmc_ocb_o2p_ongoing : 1; + uint32_t oci2spivid_ongoing : 1; + uint32_t pmc_interchip_msg_send_ongoing : 1; + uint32_t reserved_53 : 1; + uint32_t pmc_idle_enter : 1; + uint32_t pore_sw_complete : 1; + uint32_t pmc_idle_exit : 1; + uint32_t reserved_49 : 1; + uint32_t reserved_48 : 1; + uint32_t pmc_pstate_change : 1; + uint32_t pmc_sync : 1; + uint32_t pmc_protocol_ongoing : 1; + uint32_t pmc_voltage_change_ongoing : 1; + uint32_t reserved_43 : 1; + uint32_t reserved_42 : 1; + uint32_t occ_strm3_push : 1; + uint32_t occ_strm3_pull : 1; + uint32_t occ_strm2_push : 1; + uint32_t occ_strm2_pull : 1; + uint32_t occ_strm1_push : 1; + uint32_t occ_strm1_pull : 1; + uint32_t occ_strm0_push : 1; + uint32_t occ_strm0_pull : 1; + uint32_t reserved_33 : 1; + uint32_t reserved_32 : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_oimr1_and_t; + + + +typedef union ocb_oimr1_or { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t reserved_32 : 1; + uint32_t reserved_33 : 1; + uint32_t occ_strm0_pull : 1; + uint32_t occ_strm0_push : 1; + uint32_t occ_strm1_pull : 1; + uint32_t occ_strm1_push : 1; + uint32_t occ_strm2_pull : 1; + uint32_t occ_strm2_push : 1; + uint32_t occ_strm3_pull : 1; + uint32_t occ_strm3_push : 1; + uint32_t reserved_42 : 1; + uint32_t reserved_43 : 1; + uint32_t pmc_voltage_change_ongoing : 1; + uint32_t pmc_protocol_ongoing : 1; + uint32_t pmc_sync : 1; + uint32_t pmc_pstate_change : 1; + uint32_t reserved_48 : 1; + uint32_t reserved_49 : 1; + uint32_t pmc_idle_exit : 1; + uint32_t pore_sw_complete : 1; + uint32_t pmc_idle_enter : 1; + uint32_t reserved_53 : 1; + uint32_t pmc_interchip_msg_send_ongoing : 1; + uint32_t oci2spivid_ongoing : 1; + uint32_t pmc_ocb_o2p_ongoing : 1; + uint32_t pssbridge_ongoing : 1; + uint32_t pore_sbe_complete : 1; + uint32_t ipi0 : 1; + uint32_t ipi1 : 1; + uint32_t ipi2 : 1; + uint32_t ipi3 : 1; + uint32_t reserved_63 : 1; +#else + uint32_t reserved_63 : 1; + uint32_t ipi3 : 1; + uint32_t ipi2 : 1; + uint32_t ipi1 : 1; + uint32_t ipi0 : 1; + uint32_t pore_sbe_complete : 1; + uint32_t pssbridge_ongoing : 1; + uint32_t pmc_ocb_o2p_ongoing : 1; + uint32_t oci2spivid_ongoing : 1; + uint32_t pmc_interchip_msg_send_ongoing : 1; + uint32_t reserved_53 : 1; + uint32_t pmc_idle_enter : 1; + uint32_t pore_sw_complete : 1; + uint32_t pmc_idle_exit : 1; + uint32_t reserved_49 : 1; + uint32_t reserved_48 : 1; + uint32_t pmc_pstate_change : 1; + uint32_t pmc_sync : 1; + uint32_t pmc_protocol_ongoing : 1; + uint32_t pmc_voltage_change_ongoing : 1; + uint32_t reserved_43 : 1; + uint32_t reserved_42 : 1; + uint32_t occ_strm3_push : 1; + uint32_t occ_strm3_pull : 1; + uint32_t occ_strm2_push : 1; + uint32_t occ_strm2_pull : 1; + uint32_t occ_strm1_push : 1; + uint32_t occ_strm1_pull : 1; + uint32_t occ_strm0_push : 1; + uint32_t occ_strm0_pull : 1; + uint32_t reserved_33 : 1; + uint32_t reserved_32 : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_oimr1_or_t; + + + +typedef union ocb_occmisc { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t core_ext_intr : 1; + uint32_t _reserved0 : 31; +#else + uint32_t _reserved0 : 31; + uint32_t core_ext_intr : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_occmisc_t; + + + +typedef union ocb_occmisc_and { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t core_ext_intr : 1; + uint32_t _reserved0 : 31; +#else + uint32_t _reserved0 : 31; + uint32_t core_ext_intr : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_occmisc_and_t; + + + +typedef union ocb_occmisc_or { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t core_ext_intr : 1; + uint32_t _reserved0 : 31; +#else + uint32_t _reserved0 : 31; + uint32_t core_ext_intr : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_occmisc_or_t; + + + +typedef union ocb_otrn { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t timeout : 1; + uint32_t control : 1; + uint32_t auto_reload : 1; + uint32_t reserved : 13; + uint32_t timer : 16; +#else + uint32_t timer : 16; + uint32_t reserved : 13; + uint32_t auto_reload : 1; + uint32_t control : 1; + uint32_t timeout : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_otrn_t; + +#endif // __ASSEMBLER__ +#define OCB_OTRN_TIMEOUT 0x80000000 +#define OCB_OTRN_CONTROL 0x40000000 +#define OCB_OTRN_AUTO_RELOAD 0x20000000 +#define OCB_OTRN_TIMER_MASK 0x0000ffff +#ifndef __ASSEMBLER__ + + +typedef union ocb_ohtmcr { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t htm_src_sel : 2; + uint32_t htm_stop : 1; + uint32_t htm_marker_slave_adrs : 3; + uint32_t event2halt_mode : 2; + uint32_t event2halt_en : 11; + uint32_t reserved : 1; + uint32_t event2halt_halt : 1; + uint32_t _reserved0 : 11; +#else + uint32_t _reserved0 : 11; + uint32_t event2halt_halt : 1; + uint32_t reserved : 1; + uint32_t event2halt_en : 11; + uint32_t event2halt_mode : 2; + uint32_t htm_marker_slave_adrs : 3; + uint32_t htm_stop : 1; + uint32_t htm_src_sel : 2; +#endif // _BIG_ENDIAN + } fields; +} ocb_ohtmcr_t; + + + +typedef union ocb_oehdr { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t event2halt_delay : 20; + uint32_t _reserved0 : 12; +#else + uint32_t _reserved0 : 12; + uint32_t event2halt_delay : 20; +#endif // _BIG_ENDIAN + } fields; +} ocb_oehdr_t; + + + +typedef union ocb_ocbslbrn { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t pull_oci_region : 2; + uint32_t pull_start : 27; + uint32_t _reserved0 : 3; +#else + uint32_t _reserved0 : 3; + uint32_t pull_start : 27; + uint32_t pull_oci_region : 2; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocbslbrn_t; + + + +typedef union ocb_ocbshbrn { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t push_oci_region : 2; + uint32_t push_start : 27; + uint32_t _reserved0 : 3; +#else + uint32_t _reserved0 : 3; + uint32_t push_start : 27; + uint32_t push_oci_region : 2; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocbshbrn_t; + + + +typedef union ocb_ocbslcsn { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t pull_full : 1; + uint32_t pull_empty : 1; + uint32_t reserved0 : 2; + uint32_t pull_intr_action : 2; + uint32_t pull_length : 5; + uint32_t reserved1 : 2; + uint32_t pull_write_ptr : 5; + uint32_t reserved2 : 3; + uint32_t pull_read_ptr : 5; + uint32_t reserved3 : 5; + uint32_t pull_enable : 1; +#else + uint32_t pull_enable : 1; + uint32_t reserved3 : 5; + uint32_t pull_read_ptr : 5; + uint32_t reserved2 : 3; + uint32_t pull_write_ptr : 5; + uint32_t reserved1 : 2; + uint32_t pull_length : 5; + uint32_t pull_intr_action : 2; + uint32_t reserved0 : 2; + uint32_t pull_empty : 1; + uint32_t pull_full : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocbslcsn_t; + +#endif // __ASSEMBLER__ +#define OCB_OCBSLCSN_PULL_FULL 0x80000000 +#define OCB_OCBSLCSN_PULL_EMPTY 0x40000000 +#define OCB_OCBSLCSN_PULL_INTR_ACTION_MASK 0x0c000000 +#define OCB_OCBSLCSN_PULL_LENGTH_MASK 0x03e00000 +#define OCB_OCBSLCSN_PULL_WRITE_PTR_MASK 0x0007c000 +#define OCB_OCBSLCSN_PULL_READ_PTR_MASK 0x000007c0 +#define OCB_OCBSLCSN_PULL_ENABLE 0x00000001 +#ifndef __ASSEMBLER__ + + +typedef union ocb_ocbshcsn { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t push_full : 1; + uint32_t push_empty : 1; + uint32_t reserved0 : 2; + uint32_t push_intr_action : 2; + uint32_t push_length : 5; + uint32_t reserved1 : 2; + uint32_t push_write_ptr : 5; + uint32_t reserved2 : 3; + uint32_t push_read_ptr : 5; + uint32_t reserved3 : 5; + uint32_t push_enable : 1; +#else + uint32_t push_enable : 1; + uint32_t reserved3 : 5; + uint32_t push_read_ptr : 5; + uint32_t reserved2 : 3; + uint32_t push_write_ptr : 5; + uint32_t reserved1 : 2; + uint32_t push_length : 5; + uint32_t push_intr_action : 2; + uint32_t reserved0 : 2; + uint32_t push_empty : 1; + uint32_t push_full : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocbshcsn_t; + +#endif // __ASSEMBLER__ +#define OCB_OCBSHCSN_PUSH_FULL 0x80000000 +#define OCB_OCBSHCSN_PUSH_EMPTY 0x40000000 +#define OCB_OCBSHCSN_PUSH_INTR_ACTION_MASK 0x0c000000 +#define OCB_OCBSHCSN_PUSH_LENGTH_MASK 0x03e00000 +#define OCB_OCBSHCSN_PUSH_WRITE_PTR_MASK 0x0007c000 +#define OCB_OCBSHCSN_PUSH_READ_PTR_MASK 0x000007c0 +#define OCB_OCBSHCSN_PUSH_ENABLE 0x00000001 +#ifndef __ASSEMBLER__ + + +typedef union ocb_ocbslin { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t reserved : 32; +#else + uint32_t reserved : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocbslin_t; + + + +typedef union ocb_ocbshin { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t reserved : 32; +#else + uint32_t reserved : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocbshin_t; + + + +typedef union ocb_ocbsesn { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t push_read_underflow : 1; + uint32_t pull_write_overflow : 1; + uint32_t _reserved0 : 30; +#else + uint32_t _reserved0 : 30; + uint32_t pull_write_overflow : 1; + uint32_t push_read_underflow : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocbsesn_t; + + + +typedef union ocb_ocbicrn { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t allow_unsecure_pib_masters : 1; + uint32_t _reserved0 : 31; +#else + uint32_t _reserved0 : 31; + uint32_t allow_unsecure_pib_masters : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocbicrn_t; + + + +typedef union ocb_ocblwcrn { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t linear_window_enable : 1; + uint32_t spare_0 : 3; + uint32_t linear_window_bar : 16; + uint32_t linear_window_mask : 12; +#else + uint32_t linear_window_mask : 12; + uint32_t linear_window_bar : 16; + uint32_t spare_0 : 3; + uint32_t linear_window_enable : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocblwcrn_t; + + + +typedef union ocb_ocblwsrn { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t linear_window_scresp : 3; + uint32_t spare_0 : 5; + uint32_t _reserved0 : 24; +#else + uint32_t _reserved0 : 24; + uint32_t spare_0 : 5; + uint32_t linear_window_scresp : 3; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocblwsrn_t; + + + +typedef union ocb_ocblwsbrn { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t linear_window_region : 2; + uint32_t linear_window_base : 8; + uint32_t _reserved0 : 22; +#else + uint32_t _reserved0 : 22; + uint32_t linear_window_base : 8; + uint32_t linear_window_region : 2; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocblwsbrn_t; + + + +typedef union ocb_ocichsw { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t m0_priority : 2; + uint32_t m1_priority : 2; + uint32_t m2_priority : 2; + uint32_t m3_priority : 2; + uint32_t m4_priority : 2; + uint32_t m5_priority : 2; + uint32_t m6_priority : 2; + uint32_t m7_priority : 2; + uint32_t dcu_priority_sel : 1; + uint32_t icu_priority_sel : 1; + uint32_t plbarb_lockerr : 1; + uint32_t _reserved0 : 13; +#else + uint32_t _reserved0 : 13; + uint32_t plbarb_lockerr : 1; + uint32_t icu_priority_sel : 1; + uint32_t dcu_priority_sel : 1; + uint32_t m7_priority : 2; + uint32_t m6_priority : 2; + uint32_t m5_priority : 2; + uint32_t m4_priority : 2; + uint32_t m3_priority : 2; + uint32_t m2_priority : 2; + uint32_t m1_priority : 2; + uint32_t m0_priority : 2; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocichsw_t; + + + +typedef union ocb_ocr { + + 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 core_reset : 1; + uint64_t chip_reset : 1; + uint64_t system_reset : 1; + uint64_t oci_arb_reset : 1; + uint64_t trace_disable : 1; + uint64_t trace_event : 1; + uint64_t dbg_unconditional_event : 1; + uint64_t ext_interrupt : 1; + uint64_t critical_interrupt : 1; + uint64_t spare : 7; + uint64_t _reserved0 : 48; +#else + uint64_t _reserved0 : 48; + uint64_t spare : 7; + uint64_t critical_interrupt : 1; + uint64_t ext_interrupt : 1; + uint64_t dbg_unconditional_event : 1; + uint64_t trace_event : 1; + uint64_t trace_disable : 1; + uint64_t oci_arb_reset : 1; + uint64_t system_reset : 1; + uint64_t chip_reset : 1; + uint64_t core_reset : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocr_t; + + + +typedef union ocb_ocr_and { + + 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 core_reset : 1; + uint64_t chip_reset : 1; + uint64_t system_reset : 1; + uint64_t oci_arb_reset : 1; + uint64_t trace_disable : 1; + uint64_t trace_event : 1; + uint64_t dbg_unconditional_event : 1; + uint64_t ext_interrupt : 1; + uint64_t critical_interrupt : 1; + uint64_t spare : 7; + uint64_t _reserved0 : 48; +#else + uint64_t _reserved0 : 48; + uint64_t spare : 7; + uint64_t critical_interrupt : 1; + uint64_t ext_interrupt : 1; + uint64_t dbg_unconditional_event : 1; + uint64_t trace_event : 1; + uint64_t trace_disable : 1; + uint64_t oci_arb_reset : 1; + uint64_t system_reset : 1; + uint64_t chip_reset : 1; + uint64_t core_reset : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocr_and_t; + + + +typedef union ocb_ocr_or { + + 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 core_reset : 1; + uint64_t chip_reset : 1; + uint64_t system_reset : 1; + uint64_t oci_arb_reset : 1; + uint64_t trace_disable : 1; + uint64_t trace_event : 1; + uint64_t dbg_unconditional_event : 1; + uint64_t ext_interrupt : 1; + uint64_t critical_interrupt : 1; + uint64_t spare : 7; + uint64_t _reserved0 : 48; +#else + uint64_t _reserved0 : 48; + uint64_t spare : 7; + uint64_t critical_interrupt : 1; + uint64_t ext_interrupt : 1; + uint64_t dbg_unconditional_event : 1; + uint64_t trace_event : 1; + uint64_t trace_disable : 1; + uint64_t oci_arb_reset : 1; + uint64_t system_reset : 1; + uint64_t chip_reset : 1; + uint64_t core_reset : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocr_or_t; + + + +typedef union ocb_ocdbg { + + 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 : 12; + uint64_t _reserved0 : 52; +#else + uint64_t _reserved0 : 52; + uint64_t value : 12; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocdbg_t; + + + +typedef union ocb_ocbarn { + + 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 oci_region : 2; + uint64_t ocb_address : 27; + uint64_t reserved : 3; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t reserved : 3; + uint64_t ocb_address : 27; + uint64_t oci_region : 2; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocbarn_t; + +#endif // __ASSEMBLER__ +#define OCB_OCBARN_OCI_REGION_MASK SIXTYFOUR_BIT_CONSTANT(0xc000000000000000) +#define OCB_OCBARN_OCB_ADDRESS_MASK SIXTYFOUR_BIT_CONSTANT(0x3ffffff800000000) +#ifndef __ASSEMBLER__ + + +typedef union ocb_ocbcsrn { + + 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 pull_read_underflow : 1; + uint64_t push_write_overflow : 1; + uint64_t pull_read_underflow_en : 1; + uint64_t push_write_overflow_en : 1; + uint64_t ocb_stream_mode : 1; + uint64_t ocb_stream_type : 1; + uint64_t reserved1 : 2; + uint64_t ocb_oci_timeout : 1; + uint64_t ocb_oci_read_data_parity : 1; + uint64_t ocb_oci_slave_error : 1; + uint64_t ocb_pib_addr_parity_err : 1; + uint64_t ocb_pib_data_parity_err : 1; + uint64_t reserved2 : 1; + uint64_t ocb_fsm_err : 1; + uint64_t _reserved0 : 49; +#else + uint64_t _reserved0 : 49; + uint64_t ocb_fsm_err : 1; + uint64_t reserved2 : 1; + uint64_t ocb_pib_data_parity_err : 1; + uint64_t ocb_pib_addr_parity_err : 1; + uint64_t ocb_oci_slave_error : 1; + uint64_t ocb_oci_read_data_parity : 1; + uint64_t ocb_oci_timeout : 1; + uint64_t reserved1 : 2; + uint64_t ocb_stream_type : 1; + uint64_t ocb_stream_mode : 1; + uint64_t push_write_overflow_en : 1; + uint64_t pull_read_underflow_en : 1; + uint64_t push_write_overflow : 1; + uint64_t pull_read_underflow : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocbcsrn_t; + +#endif // __ASSEMBLER__ +#define OCB_OCBCSRN_PULL_READ_UNDERFLOW SIXTYFOUR_BIT_CONSTANT(0x8000000000000000) +#define OCB_OCBCSRN_PUSH_WRITE_OVERFLOW SIXTYFOUR_BIT_CONSTANT(0x4000000000000000) +#define OCB_OCBCSRN_PULL_READ_UNDERFLOW_EN SIXTYFOUR_BIT_CONSTANT(0x2000000000000000) +#define OCB_OCBCSRN_PUSH_WRITE_OVERFLOW_EN SIXTYFOUR_BIT_CONSTANT(0x1000000000000000) +#define OCB_OCBCSRN_OCB_STREAM_MODE SIXTYFOUR_BIT_CONSTANT(0x0800000000000000) +#define OCB_OCBCSRN_OCB_STREAM_TYPE SIXTYFOUR_BIT_CONSTANT(0x0400000000000000) +#define OCB_OCBCSRN_OCB_OCI_TIMEOUT SIXTYFOUR_BIT_CONSTANT(0x0080000000000000) +#define OCB_OCBCSRN_OCB_OCI_READ_DATA_PARITY SIXTYFOUR_BIT_CONSTANT(0x0040000000000000) +#define OCB_OCBCSRN_OCB_OCI_SLAVE_ERROR SIXTYFOUR_BIT_CONSTANT(0x0020000000000000) +#define OCB_OCBCSRN_OCB_PIB_ADDR_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0010000000000000) +#define OCB_OCBCSRN_OCB_PIB_DATA_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0008000000000000) +#define OCB_OCBCSRN_OCB_FSM_ERR SIXTYFOUR_BIT_CONSTANT(0x0002000000000000) +#ifndef __ASSEMBLER__ + + +typedef union ocb_ocbcsrn_and { + + 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 pull_read_underflow : 1; + uint64_t push_write_overflow : 1; + uint64_t pull_read_underflow_en : 1; + uint64_t push_write_overflow_en : 1; + uint64_t ocb_stream_mode : 1; + uint64_t ocb_stream_type : 1; + uint64_t reserved1 : 2; + uint64_t ocb_oci_timeout : 1; + uint64_t ocb_oci_read_data_parity : 1; + uint64_t ocb_oci_slave_error : 1; + uint64_t ocb_pib_addr_parity_err : 1; + uint64_t ocb_pib_data_parity_err : 1; + uint64_t reserved2 : 1; + uint64_t ocb_fsm_err : 1; + uint64_t _reserved0 : 49; +#else + uint64_t _reserved0 : 49; + uint64_t ocb_fsm_err : 1; + uint64_t reserved2 : 1; + uint64_t ocb_pib_data_parity_err : 1; + uint64_t ocb_pib_addr_parity_err : 1; + uint64_t ocb_oci_slave_error : 1; + uint64_t ocb_oci_read_data_parity : 1; + uint64_t ocb_oci_timeout : 1; + uint64_t reserved1 : 2; + uint64_t ocb_stream_type : 1; + uint64_t ocb_stream_mode : 1; + uint64_t push_write_overflow_en : 1; + uint64_t pull_read_underflow_en : 1; + uint64_t push_write_overflow : 1; + uint64_t pull_read_underflow : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocbcsrn_and_t; + + + +typedef union ocb_ocbcsrn_or { + + 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 pull_read_underflow : 1; + uint64_t push_write_overflow : 1; + uint64_t pull_read_underflow_en : 1; + uint64_t push_write_overflow_en : 1; + uint64_t ocb_stream_mode : 1; + uint64_t ocb_stream_type : 1; + uint64_t reserved1 : 2; + uint64_t ocb_oci_timeout : 1; + uint64_t ocb_oci_read_data_parity : 1; + uint64_t ocb_oci_slave_error : 1; + uint64_t ocb_pib_addr_parity_err : 1; + uint64_t ocb_pib_data_parity_err : 1; + uint64_t reserved2 : 1; + uint64_t ocb_fsm_err : 1; + uint64_t _reserved0 : 49; +#else + uint64_t _reserved0 : 49; + uint64_t ocb_fsm_err : 1; + uint64_t reserved2 : 1; + uint64_t ocb_pib_data_parity_err : 1; + uint64_t ocb_pib_addr_parity_err : 1; + uint64_t ocb_oci_slave_error : 1; + uint64_t ocb_oci_read_data_parity : 1; + uint64_t ocb_oci_timeout : 1; + uint64_t reserved1 : 2; + uint64_t ocb_stream_type : 1; + uint64_t ocb_stream_mode : 1; + uint64_t push_write_overflow_en : 1; + uint64_t pull_read_underflow_en : 1; + uint64_t push_write_overflow : 1; + uint64_t pull_read_underflow : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocbcsrn_or_t; + + + +typedef union ocb_ocbesrn { + + 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 ocb_error_addr : 32; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t ocb_error_addr : 32; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocbesrn_t; + + + +typedef union ocb_ocbdrn { + + 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 ocb_data : 64; +#else + uint64_t ocb_data : 64; +#endif // _BIG_ENDIAN + } fields; +} ocb_ocbdrn_t; + + + +typedef union ocb_osbcr { + + 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 occ_block_unsecure_masters : 1; + uint64_t _reserved0 : 63; +#else + uint64_t _reserved0 : 63; + uint64_t occ_block_unsecure_masters : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_osbcr_t; + + + +typedef union ocb_otdcr { + + 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 trace_bus_en : 1; + uint64_t ocb_trace_mux_sel : 1; + uint64_t occ_trace_mux_sel : 2; + uint64_t oci_trace_mux_sel : 4; + uint64_t _reserved0 : 56; +#else + uint64_t _reserved0 : 56; + uint64_t oci_trace_mux_sel : 4; + uint64_t occ_trace_mux_sel : 2; + uint64_t ocb_trace_mux_sel : 1; + uint64_t trace_bus_en : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_otdcr_t; + + + +typedef union ocb_oppcinj { + + 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 oci_err_inj_dcu : 1; + uint64_t oci_err_inj_icu : 1; + uint64_t oci_err_inj_ce_ue : 1; + uint64_t oci_err_inj_singl_cont : 1; + uint64_t _reserved0 : 60; +#else + uint64_t _reserved0 : 60; + uint64_t oci_err_inj_singl_cont : 1; + uint64_t oci_err_inj_ce_ue : 1; + uint64_t oci_err_inj_icu : 1; + uint64_t oci_err_inj_dcu : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_oppcinj_t; + + + +typedef union ocb_occlfir { + + 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 occ_fw0 : 1; + uint64_t occ_fw1 : 1; + uint64_t occ_fw2 : 1; + uint64_t occ_fw3 : 1; + uint64_t pmc_pore_sw_malf : 1; + uint64_t pmc_occ_hb_malf : 1; + uint64_t pore_gpe0_fatal_err : 1; + uint64_t pore_gpe1_fatal_err : 1; + uint64_t ocb_error : 1; + uint64_t pmc_error : 1; + uint64_t srt_ue : 1; + uint64_t srt_ce : 1; + uint64_t srt_read_error : 1; + uint64_t srt_write_error : 1; + uint64_t srt_oci_write_data_parity : 1; + uint64_t srt_oci_be_parity_err : 1; + uint64_t srt_oci_addr_parity_err : 1; + uint64_t pore_sw_error_err : 1; + uint64_t pore_gpe0_error_err : 1; + uint64_t pore_gpe1_error_err : 1; + uint64_t external_trap : 1; + uint64_t ppc405_core_reset : 1; + uint64_t ppc405_chip_reset : 1; + uint64_t ppc405_system_reset : 1; + uint64_t ppc405_dbgmsrwe : 1; + uint64_t ppc405_dbgstopack : 1; + uint64_t ocb_db_oci_timeout : 1; + uint64_t ocb_db_oci_read_data_parity : 1; + uint64_t ocb_db_oci_slave_error : 1; + uint64_t ocb_pib_addr_parity_err : 1; + uint64_t ocb_db_pib_data_parity_err : 1; + uint64_t ocb_idc0_error : 1; + uint64_t ocb_idc1_error : 1; + uint64_t ocb_idc2_error : 1; + uint64_t ocb_idc3_error : 1; + uint64_t srt_fsm_err : 1; + uint64_t jtagacc_err : 1; + uint64_t ocb_dw_err : 1; + uint64_t c405_ecc_ue : 1; + uint64_t c405_ecc_ce : 1; + uint64_t c405_oci_machinecheck : 1; + uint64_t sram_spare_direct_error0 : 1; + uint64_t sram_spare_direct_error1 : 1; + uint64_t sram_spare_direct_error2 : 1; + uint64_t sram_spare_direct_error3 : 1; + uint64_t slw_ocislv_err : 1; + uint64_t gpe_ocislv_err : 1; + uint64_t ocb_ocislv_err : 1; + uint64_t c405icu_m_timeout : 1; + uint64_t c405dcu_m_timeout : 1; + uint64_t spare_fir : 12; + uint64_t fir_parity_err_dup : 1; + uint64_t fir_parity_err : 1; +#else + uint64_t fir_parity_err : 1; + uint64_t fir_parity_err_dup : 1; + uint64_t spare_fir : 12; + uint64_t c405dcu_m_timeout : 1; + uint64_t c405icu_m_timeout : 1; + uint64_t ocb_ocislv_err : 1; + uint64_t gpe_ocislv_err : 1; + uint64_t slw_ocislv_err : 1; + uint64_t sram_spare_direct_error3 : 1; + uint64_t sram_spare_direct_error2 : 1; + uint64_t sram_spare_direct_error1 : 1; + uint64_t sram_spare_direct_error0 : 1; + uint64_t c405_oci_machinecheck : 1; + uint64_t c405_ecc_ce : 1; + uint64_t c405_ecc_ue : 1; + uint64_t ocb_dw_err : 1; + uint64_t jtagacc_err : 1; + uint64_t srt_fsm_err : 1; + uint64_t ocb_idc3_error : 1; + uint64_t ocb_idc2_error : 1; + uint64_t ocb_idc1_error : 1; + uint64_t ocb_idc0_error : 1; + uint64_t ocb_db_pib_data_parity_err : 1; + uint64_t ocb_pib_addr_parity_err : 1; + uint64_t ocb_db_oci_slave_error : 1; + uint64_t ocb_db_oci_read_data_parity : 1; + uint64_t ocb_db_oci_timeout : 1; + uint64_t ppc405_dbgstopack : 1; + uint64_t ppc405_dbgmsrwe : 1; + uint64_t ppc405_system_reset : 1; + uint64_t ppc405_chip_reset : 1; + uint64_t ppc405_core_reset : 1; + uint64_t external_trap : 1; + uint64_t pore_gpe1_error_err : 1; + uint64_t pore_gpe0_error_err : 1; + uint64_t pore_sw_error_err : 1; + uint64_t srt_oci_addr_parity_err : 1; + uint64_t srt_oci_be_parity_err : 1; + uint64_t srt_oci_write_data_parity : 1; + uint64_t srt_write_error : 1; + uint64_t srt_read_error : 1; + uint64_t srt_ce : 1; + uint64_t srt_ue : 1; + uint64_t pmc_error : 1; + uint64_t ocb_error : 1; + uint64_t pore_gpe1_fatal_err : 1; + uint64_t pore_gpe0_fatal_err : 1; + uint64_t pmc_occ_hb_malf : 1; + uint64_t pmc_pore_sw_malf : 1; + uint64_t occ_fw3 : 1; + uint64_t occ_fw2 : 1; + uint64_t occ_fw1 : 1; + uint64_t occ_fw0 : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_occlfir_t; + +#endif // __ASSEMBLER__ +#define OCB_OCCLFIR_OCC_FW0 SIXTYFOUR_BIT_CONSTANT(0x8000000000000000) +#define OCB_OCCLFIR_OCC_FW1 SIXTYFOUR_BIT_CONSTANT(0x4000000000000000) +#define OCB_OCCLFIR_OCC_FW2 SIXTYFOUR_BIT_CONSTANT(0x2000000000000000) +#define OCB_OCCLFIR_OCC_FW3 SIXTYFOUR_BIT_CONSTANT(0x1000000000000000) +#define OCB_OCCLFIR_PMC_PORE_SW_MALF SIXTYFOUR_BIT_CONSTANT(0x0800000000000000) +#define OCB_OCCLFIR_PMC_OCC_HB_MALF SIXTYFOUR_BIT_CONSTANT(0x0400000000000000) +#define OCB_OCCLFIR_PORE_GPE0_FATAL_ERR SIXTYFOUR_BIT_CONSTANT(0x0200000000000000) +#define OCB_OCCLFIR_PORE_GPE1_FATAL_ERR SIXTYFOUR_BIT_CONSTANT(0x0100000000000000) +#define OCB_OCCLFIR_OCB_ERROR SIXTYFOUR_BIT_CONSTANT(0x0080000000000000) +#define OCB_OCCLFIR_PMC_ERROR SIXTYFOUR_BIT_CONSTANT(0x0040000000000000) +#define OCB_OCCLFIR_SRT_UE SIXTYFOUR_BIT_CONSTANT(0x0020000000000000) +#define OCB_OCCLFIR_SRT_CE SIXTYFOUR_BIT_CONSTANT(0x0010000000000000) +#define OCB_OCCLFIR_SRT_READ_ERROR SIXTYFOUR_BIT_CONSTANT(0x0008000000000000) +#define OCB_OCCLFIR_SRT_WRITE_ERROR SIXTYFOUR_BIT_CONSTANT(0x0004000000000000) +#define OCB_OCCLFIR_SRT_OCI_WRITE_DATA_PARITY SIXTYFOUR_BIT_CONSTANT(0x0002000000000000) +#define OCB_OCCLFIR_SRT_OCI_BE_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0001000000000000) +#define OCB_OCCLFIR_SRT_OCI_ADDR_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0000800000000000) +#define OCB_OCCLFIR_PORE_SW_ERROR_ERR SIXTYFOUR_BIT_CONSTANT(0x0000400000000000) +#define OCB_OCCLFIR_PORE_GPE0_ERROR_ERR SIXTYFOUR_BIT_CONSTANT(0x0000200000000000) +#define OCB_OCCLFIR_PORE_GPE1_ERROR_ERR SIXTYFOUR_BIT_CONSTANT(0x0000100000000000) +#define OCB_OCCLFIR_EXTERNAL_TRAP SIXTYFOUR_BIT_CONSTANT(0x0000080000000000) +#define OCB_OCCLFIR_PPC405_CORE_RESET SIXTYFOUR_BIT_CONSTANT(0x0000040000000000) +#define OCB_OCCLFIR_PPC405_CHIP_RESET SIXTYFOUR_BIT_CONSTANT(0x0000020000000000) +#define OCB_OCCLFIR_PPC405_SYSTEM_RESET SIXTYFOUR_BIT_CONSTANT(0x0000010000000000) +#define OCB_OCCLFIR_PPC405_DBGMSRWE SIXTYFOUR_BIT_CONSTANT(0x0000008000000000) +#define OCB_OCCLFIR_PPC405_DBGSTOPACK SIXTYFOUR_BIT_CONSTANT(0x0000004000000000) +#define OCB_OCCLFIR_OCB_DB_OCI_TIMEOUT SIXTYFOUR_BIT_CONSTANT(0x0000002000000000) +#define OCB_OCCLFIR_OCB_DB_OCI_READ_DATA_PARITY SIXTYFOUR_BIT_CONSTANT(0x0000001000000000) +#define OCB_OCCLFIR_OCB_DB_OCI_SLAVE_ERROR SIXTYFOUR_BIT_CONSTANT(0x0000000800000000) +#define OCB_OCCLFIR_OCB_PIB_ADDR_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000400000000) +#define OCB_OCCLFIR_OCB_DB_PIB_DATA_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000200000000) +#define OCB_OCCLFIR_OCB_IDC0_ERROR SIXTYFOUR_BIT_CONSTANT(0x0000000100000000) +#define OCB_OCCLFIR_OCB_IDC1_ERROR SIXTYFOUR_BIT_CONSTANT(0x0000000080000000) +#define OCB_OCCLFIR_OCB_IDC2_ERROR SIXTYFOUR_BIT_CONSTANT(0x0000000040000000) +#define OCB_OCCLFIR_OCB_IDC3_ERROR SIXTYFOUR_BIT_CONSTANT(0x0000000020000000) +#define OCB_OCCLFIR_SRT_FSM_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000010000000) +#define OCB_OCCLFIR_JTAGACC_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000008000000) +#define OCB_OCCLFIR_OCB_DW_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000004000000) +#define OCB_OCCLFIR_C405_ECC_UE SIXTYFOUR_BIT_CONSTANT(0x0000000002000000) +#define OCB_OCCLFIR_C405_ECC_CE SIXTYFOUR_BIT_CONSTANT(0x0000000001000000) +#define OCB_OCCLFIR_C405_OCI_MACHINECHECK SIXTYFOUR_BIT_CONSTANT(0x0000000000800000) +#define OCB_OCCLFIR_SRAM_SPARE_DIRECT_ERROR0 SIXTYFOUR_BIT_CONSTANT(0x0000000000400000) +#define OCB_OCCLFIR_SRAM_SPARE_DIRECT_ERROR1 SIXTYFOUR_BIT_CONSTANT(0x0000000000200000) +#define OCB_OCCLFIR_SRAM_SPARE_DIRECT_ERROR2 SIXTYFOUR_BIT_CONSTANT(0x0000000000100000) +#define OCB_OCCLFIR_SRAM_SPARE_DIRECT_ERROR3 SIXTYFOUR_BIT_CONSTANT(0x0000000000080000) +#define OCB_OCCLFIR_SLW_OCISLV_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000000040000) +#define OCB_OCCLFIR_GPE_OCISLV_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000000020000) +#define OCB_OCCLFIR_OCB_OCISLV_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000000010000) +#define OCB_OCCLFIR_C405ICU_M_TIMEOUT SIXTYFOUR_BIT_CONSTANT(0x0000000000008000) +#define OCB_OCCLFIR_C405DCU_M_TIMEOUT SIXTYFOUR_BIT_CONSTANT(0x0000000000004000) +#define OCB_OCCLFIR_SPARE_FIR_MASK SIXTYFOUR_BIT_CONSTANT(0x0000000000003ffc) +#define OCB_OCCLFIR_FIR_PARITY_ERR_DUP SIXTYFOUR_BIT_CONSTANT(0x0000000000000002) +#define OCB_OCCLFIR_FIR_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000000000001) +#ifndef __ASSEMBLER__ + + +typedef union ocb_occlfir_and { + + 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 occ_fw0 : 1; + uint64_t occ_fw1 : 1; + uint64_t occ_fw2 : 1; + uint64_t occ_fw3 : 1; + uint64_t pmc_pore_sw_malf : 1; + uint64_t pmc_occ_hb_malf : 1; + uint64_t pore_gpe0_fatal_err : 1; + uint64_t pore_gpe1_fatal_err : 1; + uint64_t ocb_error : 1; + uint64_t pmc_error : 1; + uint64_t srt_ue : 1; + uint64_t srt_ce : 1; + uint64_t srt_read_error : 1; + uint64_t srt_write_error : 1; + uint64_t srt_oci_write_data_parity : 1; + uint64_t srt_oci_be_parity_err : 1; + uint64_t srt_oci_addr_parity_err : 1; + uint64_t pore_sw_error_err : 1; + uint64_t pore_gpe0_error_err : 1; + uint64_t pore_gpe1_error_err : 1; + uint64_t external_trap : 1; + uint64_t ppc405_core_reset : 1; + uint64_t ppc405_chip_reset : 1; + uint64_t ppc405_system_reset : 1; + uint64_t ppc405_dbgmsrwe : 1; + uint64_t ppc405_dbgstopack : 1; + uint64_t ocb_db_oci_timeout : 1; + uint64_t ocb_db_oci_read_data_parity : 1; + uint64_t ocb_db_oci_slave_error : 1; + uint64_t ocb_pib_addr_parity_err : 1; + uint64_t ocb_db_pib_data_parity_err : 1; + uint64_t ocb_idc0_error : 1; + uint64_t ocb_idc1_error : 1; + uint64_t ocb_idc2_error : 1; + uint64_t ocb_idc3_error : 1; + uint64_t srt_fsm_err : 1; + uint64_t jtagacc_err : 1; + uint64_t ocb_dw_err : 1; + uint64_t c405_ecc_ue : 1; + uint64_t c405_ecc_ce : 1; + uint64_t c405_oci_machinecheck : 1; + uint64_t sram_spare_direct_error0 : 1; + uint64_t sram_spare_direct_error1 : 1; + uint64_t sram_spare_direct_error2 : 1; + uint64_t sram_spare_direct_error3 : 1; + uint64_t slw_ocislv_err : 1; + uint64_t gpe_ocislv_err : 1; + uint64_t ocb_ocislv_err : 1; + uint64_t c405icu_m_timeout : 1; + uint64_t c405dcu_m_timeout : 1; + uint64_t spare_fir : 12; + uint64_t fir_parity_err_dup : 1; + uint64_t fir_parity_err : 1; +#else + uint64_t fir_parity_err : 1; + uint64_t fir_parity_err_dup : 1; + uint64_t spare_fir : 12; + uint64_t c405dcu_m_timeout : 1; + uint64_t c405icu_m_timeout : 1; + uint64_t ocb_ocislv_err : 1; + uint64_t gpe_ocislv_err : 1; + uint64_t slw_ocislv_err : 1; + uint64_t sram_spare_direct_error3 : 1; + uint64_t sram_spare_direct_error2 : 1; + uint64_t sram_spare_direct_error1 : 1; + uint64_t sram_spare_direct_error0 : 1; + uint64_t c405_oci_machinecheck : 1; + uint64_t c405_ecc_ce : 1; + uint64_t c405_ecc_ue : 1; + uint64_t ocb_dw_err : 1; + uint64_t jtagacc_err : 1; + uint64_t srt_fsm_err : 1; + uint64_t ocb_idc3_error : 1; + uint64_t ocb_idc2_error : 1; + uint64_t ocb_idc1_error : 1; + uint64_t ocb_idc0_error : 1; + uint64_t ocb_db_pib_data_parity_err : 1; + uint64_t ocb_pib_addr_parity_err : 1; + uint64_t ocb_db_oci_slave_error : 1; + uint64_t ocb_db_oci_read_data_parity : 1; + uint64_t ocb_db_oci_timeout : 1; + uint64_t ppc405_dbgstopack : 1; + uint64_t ppc405_dbgmsrwe : 1; + uint64_t ppc405_system_reset : 1; + uint64_t ppc405_chip_reset : 1; + uint64_t ppc405_core_reset : 1; + uint64_t external_trap : 1; + uint64_t pore_gpe1_error_err : 1; + uint64_t pore_gpe0_error_err : 1; + uint64_t pore_sw_error_err : 1; + uint64_t srt_oci_addr_parity_err : 1; + uint64_t srt_oci_be_parity_err : 1; + uint64_t srt_oci_write_data_parity : 1; + uint64_t srt_write_error : 1; + uint64_t srt_read_error : 1; + uint64_t srt_ce : 1; + uint64_t srt_ue : 1; + uint64_t pmc_error : 1; + uint64_t ocb_error : 1; + uint64_t pore_gpe1_fatal_err : 1; + uint64_t pore_gpe0_fatal_err : 1; + uint64_t pmc_occ_hb_malf : 1; + uint64_t pmc_pore_sw_malf : 1; + uint64_t occ_fw3 : 1; + uint64_t occ_fw2 : 1; + uint64_t occ_fw1 : 1; + uint64_t occ_fw0 : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_occlfir_and_t; + + + +typedef union ocb_occlfir_or { + + 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 occ_fw0 : 1; + uint64_t occ_fw1 : 1; + uint64_t occ_fw2 : 1; + uint64_t occ_fw3 : 1; + uint64_t pmc_pore_sw_malf : 1; + uint64_t pmc_occ_hb_malf : 1; + uint64_t pore_gpe0_fatal_err : 1; + uint64_t pore_gpe1_fatal_err : 1; + uint64_t ocb_error : 1; + uint64_t pmc_error : 1; + uint64_t srt_ue : 1; + uint64_t srt_ce : 1; + uint64_t srt_read_error : 1; + uint64_t srt_write_error : 1; + uint64_t srt_oci_write_data_parity : 1; + uint64_t srt_oci_be_parity_err : 1; + uint64_t srt_oci_addr_parity_err : 1; + uint64_t pore_sw_error_err : 1; + uint64_t pore_gpe0_error_err : 1; + uint64_t pore_gpe1_error_err : 1; + uint64_t external_trap : 1; + uint64_t ppc405_core_reset : 1; + uint64_t ppc405_chip_reset : 1; + uint64_t ppc405_system_reset : 1; + uint64_t ppc405_dbgmsrwe : 1; + uint64_t ppc405_dbgstopack : 1; + uint64_t ocb_db_oci_timeout : 1; + uint64_t ocb_db_oci_read_data_parity : 1; + uint64_t ocb_db_oci_slave_error : 1; + uint64_t ocb_pib_addr_parity_err : 1; + uint64_t ocb_db_pib_data_parity_err : 1; + uint64_t ocb_idc0_error : 1; + uint64_t ocb_idc1_error : 1; + uint64_t ocb_idc2_error : 1; + uint64_t ocb_idc3_error : 1; + uint64_t srt_fsm_err : 1; + uint64_t jtagacc_err : 1; + uint64_t ocb_dw_err : 1; + uint64_t c405_ecc_ue : 1; + uint64_t c405_ecc_ce : 1; + uint64_t c405_oci_machinecheck : 1; + uint64_t sram_spare_direct_error0 : 1; + uint64_t sram_spare_direct_error1 : 1; + uint64_t sram_spare_direct_error2 : 1; + uint64_t sram_spare_direct_error3 : 1; + uint64_t slw_ocislv_err : 1; + uint64_t gpe_ocislv_err : 1; + uint64_t ocb_ocislv_err : 1; + uint64_t c405icu_m_timeout : 1; + uint64_t c405dcu_m_timeout : 1; + uint64_t spare_fir : 12; + uint64_t fir_parity_err_dup : 1; + uint64_t fir_parity_err : 1; +#else + uint64_t fir_parity_err : 1; + uint64_t fir_parity_err_dup : 1; + uint64_t spare_fir : 12; + uint64_t c405dcu_m_timeout : 1; + uint64_t c405icu_m_timeout : 1; + uint64_t ocb_ocislv_err : 1; + uint64_t gpe_ocislv_err : 1; + uint64_t slw_ocislv_err : 1; + uint64_t sram_spare_direct_error3 : 1; + uint64_t sram_spare_direct_error2 : 1; + uint64_t sram_spare_direct_error1 : 1; + uint64_t sram_spare_direct_error0 : 1; + uint64_t c405_oci_machinecheck : 1; + uint64_t c405_ecc_ce : 1; + uint64_t c405_ecc_ue : 1; + uint64_t ocb_dw_err : 1; + uint64_t jtagacc_err : 1; + uint64_t srt_fsm_err : 1; + uint64_t ocb_idc3_error : 1; + uint64_t ocb_idc2_error : 1; + uint64_t ocb_idc1_error : 1; + uint64_t ocb_idc0_error : 1; + uint64_t ocb_db_pib_data_parity_err : 1; + uint64_t ocb_pib_addr_parity_err : 1; + uint64_t ocb_db_oci_slave_error : 1; + uint64_t ocb_db_oci_read_data_parity : 1; + uint64_t ocb_db_oci_timeout : 1; + uint64_t ppc405_dbgstopack : 1; + uint64_t ppc405_dbgmsrwe : 1; + uint64_t ppc405_system_reset : 1; + uint64_t ppc405_chip_reset : 1; + uint64_t ppc405_core_reset : 1; + uint64_t external_trap : 1; + uint64_t pore_gpe1_error_err : 1; + uint64_t pore_gpe0_error_err : 1; + uint64_t pore_sw_error_err : 1; + uint64_t srt_oci_addr_parity_err : 1; + uint64_t srt_oci_be_parity_err : 1; + uint64_t srt_oci_write_data_parity : 1; + uint64_t srt_write_error : 1; + uint64_t srt_read_error : 1; + uint64_t srt_ce : 1; + uint64_t srt_ue : 1; + uint64_t pmc_error : 1; + uint64_t ocb_error : 1; + uint64_t pore_gpe1_fatal_err : 1; + uint64_t pore_gpe0_fatal_err : 1; + uint64_t pmc_occ_hb_malf : 1; + uint64_t pmc_pore_sw_malf : 1; + uint64_t occ_fw3 : 1; + uint64_t occ_fw2 : 1; + uint64_t occ_fw1 : 1; + uint64_t occ_fw0 : 1; +#endif // _BIG_ENDIAN + } fields; +} ocb_occlfir_or_t; + + + +typedef union ocb_occlfirmask { + + 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; +} ocb_occlfirmask_t; + + + +typedef union ocb_occlfirmask_and { + + 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; +} ocb_occlfirmask_and_t; + + + +typedef union ocb_occlfirmask_or { + + 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; +} ocb_occlfirmask_or_t; + + + +typedef union ocb_occlfiract0 { + + 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; +} ocb_occlfiract0_t; + + + +typedef union ocb_occlfiract1 { + + 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; +} ocb_occlfiract1_t; + + + +typedef union ocb_occerrrpt { + + 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 sram_cerrrpt : 10; + uint64_t jtagacc_cerrrpt : 6; + uint64_t c405_dcu_ecc_ue_cerrrpt : 1; + uint64_t c405_dcu_ecc_ce_cerrrpt : 1; + uint64_t c405_icu_ecc_ue_cerrrpt : 1; + uint64_t c405_icu_ecc_ce_cerrrpt : 1; + uint64_t slw_ocislv_err : 7; + uint64_t gpe_ocislv_err : 7; + uint64_t ocb_ocislv_err : 6; + uint64_t _reserved0 : 24; +#else + uint64_t _reserved0 : 24; + uint64_t ocb_ocislv_err : 6; + uint64_t gpe_ocislv_err : 7; + uint64_t slw_ocislv_err : 7; + uint64_t c405_icu_ecc_ce_cerrrpt : 1; + uint64_t c405_icu_ecc_ue_cerrrpt : 1; + uint64_t c405_dcu_ecc_ce_cerrrpt : 1; + uint64_t c405_dcu_ecc_ue_cerrrpt : 1; + uint64_t jtagacc_cerrrpt : 6; + uint64_t sram_cerrrpt : 10; +#endif // _BIG_ENDIAN + } fields; +} ocb_occerrrpt_t; + + + +typedef union ocb_scan_dummy_1 { + + 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 _reserved0 : 48; + uint64_t value : 16; +#else + uint64_t value : 16; + uint64_t _reserved0 : 48; +#endif // _BIG_ENDIAN + } fields; +} ocb_scan_dummy_1_t; + + + +typedef union ocb_scan_dummy_2 { + + 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 _reserved0 : 63; + uint64_t value : 1; +#else + uint64_t value : 1; + uint64_t _reserved0 : 63; +#endif // _BIG_ENDIAN + } fields; +} ocb_scan_dummy_2_t; + + +#endif // __ASSEMBLER__ +#endif // __OCB_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/ocb_register_addresses.h b/src/ssx/pgp/registers/ocb_register_addresses.h new file mode 100755 index 0000000..3290e59 --- /dev/null +++ b/src/ssx/pgp/registers/ocb_register_addresses.h @@ -0,0 +1,148 @@ +#ifndef __OCB_REGISTER_ADDRESSES_H__ +#define __OCB_REGISTER_ADDRESSES_H__ + +// $Id: ocb_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/ocb_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ocb_register_addresses.h +/// \brief Symbolic addresses for the OCB unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define OCB_OCI_BASE 0x40050000 +#define OCB_OITR0 0x40050040 +#define OCB_OIEPR0 0x40050048 +#define OCB_OCIR0 0x40050050 +#define OCB_ONISR0 0x40050058 +#define OCB_OUDER0 0x40050060 +#define OCB_OCISR0 0x40050068 +#define OCB_ODHER0 0x40050070 +#define OCB_OISR0 0x40050000 +#define OCB_OISR0_AND 0x40050008 +#define OCB_OISR0_OR 0x40050010 +#define OCB_OIMR0 0x40050020 +#define OCB_OIMR0_AND 0x40050028 +#define OCB_OIMR0_OR 0x40050030 +#define OCB_OITR1 0x400500c0 +#define OCB_OIEPR1 0x400500c8 +#define OCB_OCIR1 0x400500d0 +#define OCB_ONISR1 0x400500d8 +#define OCB_OUDER1 0x400500e0 +#define OCB_OCISR1 0x400500e8 +#define OCB_ODHER1 0x400500f0 +#define OCB_OISR1 0x40050080 +#define OCB_OISR1_AND 0x40050088 +#define OCB_OISR1_OR 0x40050090 +#define OCB_OIMR1 0x400500a0 +#define OCB_OIMR1_AND 0x400500a8 +#define OCB_OIMR1_OR 0x400500b0 +#define OCB_OCCMISC 0x40050100 +#define OCB_OCCMISC_AND 0x40050108 +#define OCB_OCCMISC_OR 0x40050110 +#define OCB_OTRN(n) (OCB_OTR0 + ((OCB_OTR1 - OCB_OTR0) * (n))) +#define OCB_OTR0 0x40050800 +#define OCB_OTR1 0x40050808 +#define OCB_OHTMCR 0x40050118 +#define OCB_OEHDR 0x40050120 +#define OCB_OCBSLBRN(n) (OCB_OCBSLBR0 + ((OCB_OCBSLBR1 - OCB_OCBSLBR0) * (n))) +#define OCB_OCBSLBR0 0x40051000 +#define OCB_OCBSLBR1 0x40051080 +#define OCB_OCBSLBR2 0x40051100 +#define OCB_OCBSHBRN(n) (OCB_OCBSHBR0 + ((OCB_OCBSHBR1 - OCB_OCBSHBR0) * (n))) +#define OCB_OCBSHBR0 0x40051018 +#define OCB_OCBSHBR1 0x40051098 +#define OCB_OCBSHBR2 0x40051118 +#define OCB_OCBSLCSN(n) (OCB_OCBSLCS0 + ((OCB_OCBSLCS1 - OCB_OCBSLCS0) * (n))) +#define OCB_OCBSLCS0 0x40051008 +#define OCB_OCBSLCS1 0x40051088 +#define OCB_OCBSLCS2 0x40051108 +#define OCB_OCBSHCSN(n) (OCB_OCBSHCS0 + ((OCB_OCBSHCS1 - OCB_OCBSHCS0) * (n))) +#define OCB_OCBSHCS0 0x40051020 +#define OCB_OCBSHCS1 0x400510a0 +#define OCB_OCBSHCS2 0x40051120 +#define OCB_OCBSLIN(n) (OCB_OCBSLI0 + ((OCB_OCBSLI1 - OCB_OCBSLI0) * (n))) +#define OCB_OCBSLI0 0x40051010 +#define OCB_OCBSLI1 0x40051090 +#define OCB_OCBSLI2 0x40051110 +#define OCB_OCBSHIN(n) (OCB_OCBSHI0 + ((OCB_OCBSHI1 - OCB_OCBSHI0) * (n))) +#define OCB_OCBSHI0 0x40051028 +#define OCB_OCBSHI1 0x400510a8 +#define OCB_OCBSHI2 0x40051128 +#define OCB_OCBSESN(n) (OCB_OCBSES0 + ((OCB_OCBSES1 - OCB_OCBSES0) * (n))) +#define OCB_OCBSES0 0x40051030 +#define OCB_OCBSES1 0x400510b0 +#define OCB_OCBSES2 0x40051130 +#define OCB_OCBICRN(n) (OCB_OCBICR0 + ((OCB_OCBICR1 - OCB_OCBICR0) * (n))) +#define OCB_OCBICR0 0x40051038 +#define OCB_OCBICR1 0x400510b8 +#define OCB_OCBICR2 0x40051138 +#define OCB_OCBLWCRN(n) (OCB_OCBLWCR0 + ((OCB_OCBLWCR1 - OCB_OCBLWCR0) * (n))) +#define OCB_OCBLWCR0 0x40051040 +#define OCB_OCBLWCR1 0x400510c0 +#define OCB_OCBLWCR2 0x40051140 +#define OCB_OCBLWSRN(n) (OCB_OCBLWSR0 + ((OCB_OCBLWSR1 - OCB_OCBLWSR0) * (n))) +#define OCB_OCBLWSR0 0x40051050 +#define OCB_OCBLWSR1 0x400510d0 +#define OCB_OCBLWSR2 0x40051150 +#define OCB_OCBLWSBRN(n) (OCB_OCBLWSBR0 + ((OCB_OCBLWSBR1 - OCB_OCBLWSBR0) * (n))) +#define OCB_OCBLWSBR0 0x40051060 +#define OCB_OCBLWSBR1 0x400510e0 +#define OCB_OCBLWSBR2 0x40051160 +#define OCB_OCICHSW 0x40050128 +#define OCB_PIB_BASE 0x0006a000 +#define OCB_OCR 0x0006b000 +#define OCB_OCR_AND 0x0006b001 +#define OCB_OCR_OR 0x0006b002 +#define OCB_OCDBG 0x0006b003 +#define OCB_OCBARN(n) (OCB_OCBAR0 + ((OCB_OCBAR1 - OCB_OCBAR0) * (n))) +#define OCB_OCBAR0 0x0006b010 +#define OCB_OCBAR1 0x0006b030 +#define OCB_OCBAR2 0x0006b050 +#define OCB_OCBAR3 0x0006b070 +#define OCB_OCBCSRN(n) (OCB_OCBCSR0 + ((OCB_OCBCSR1 - OCB_OCBCSR0) * (n))) +#define OCB_OCBCSR0 0x0006b011 +#define OCB_OCBCSR1 0x0006b031 +#define OCB_OCBCSR2 0x0006b051 +#define OCB_OCBCSR3 0x0006b071 +#define OCB_OCBCSRN_AND(n) (OCB_OCBCSR0_AND + ((OCB_OCBCSR1_AND - OCB_OCBCSR0_AND) * (n))) +#define OCB_OCBCSR0_AND 0x0006b012 +#define OCB_OCBCSR1_AND 0x0006b032 +#define OCB_OCBCSR2_AND 0x0006b052 +#define OCB_OCBCSR3_AND 0x0006b072 +#define OCB_OCBCSRN_OR(n) (OCB_OCBCSR0_OR + ((OCB_OCBCSR1_OR - OCB_OCBCSR0_OR) * (n))) +#define OCB_OCBCSR0_OR 0x0006b013 +#define OCB_OCBCSR1_OR 0x0006b033 +#define OCB_OCBCSR2_OR 0x0006b053 +#define OCB_OCBCSR3_OR 0x0006b073 +#define OCB_OCBESRN(n) (OCB_OCBESR0 + ((OCB_OCBESR1 - OCB_OCBESR0) * (n))) +#define OCB_OCBESR0 0x0006b014 +#define OCB_OCBESR1 0x0006b034 +#define OCB_OCBESR2 0x0006b054 +#define OCB_OCBESR3 0x0006b074 +#define OCB_OCBDRN(n) (OCB_OCBDR0 + ((OCB_OCBDR1 - OCB_OCBDR0) * (n))) +#define OCB_OCBDR0 0x0006b015 +#define OCB_OCBDR1 0x0006b035 +#define OCB_OCBDR2 0x0006b055 +#define OCB_OCBDR3 0x0006b075 +#define OCB_OSBCR 0x0006b100 +#define OCB_OTDCR 0x0006b110 +#define OCB_OPPCINJ 0x0006b111 +#define OCB_FIRPIB_BASE 0x01010800 +#define OCB_OCCLFIR 0x01010800 +#define OCB_OCCLFIR_AND 0x01010801 +#define OCB_OCCLFIR_OR 0x01010802 +#define OCB_OCCLFIRMASK 0x01010803 +#define OCB_OCCLFIRMASK_AND 0x01010804 +#define OCB_OCCLFIRMASK_OR 0x01010805 +#define OCB_OCCLFIRACT0 0x01010806 +#define OCB_OCCLFIRACT1 0x01010807 +#define OCB_OCCERRRPT 0x0101080a + +#endif // __OCB_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/oha_firmware_registers.h b/src/ssx/pgp/registers/oha_firmware_registers.h new file mode 100755 index 0000000..cba1500 --- /dev/null +++ b/src/ssx/pgp/registers/oha_firmware_registers.h @@ -0,0 +1,1248 @@ +#ifndef __OHA_FIRMWARE_REGISTERS_H__ +#define __OHA_FIRMWARE_REGISTERS_H__ + +// $Id: oha_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/oha_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file oha_firmware_registers.h +/// \brief C register structs for the OHA unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union oha_activity_sample_mode_reg { + + 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 enable_activity_sampling : 1; + uint64_t enable_ppt_trace : 1; + uint64_t l2_act_count_is_free_running : 1; + uint64_t l3_act_count_is_free_running : 1; + uint64_t activity_sample_l2l3_enable : 1; + uint64_t core_activity_sample_enable : 1; + uint64_t disable_activity_proxy_reset : 1; + uint64_t power_proxy_activity_range_select_vcs : 5; + uint64_t power_proxy_activity_range_select_vdd : 5; + uint64_t memory_activity_range_select : 4; + uint64_t avg_freq_counter_scaler : 3; + uint64_t ppt_trace_timer_match_val : 11; + uint64_t disable_ppt_int_timer_reset : 1; + uint64_t ppt_int_timer_select : 2; + uint64_t disable_ppt_cycle_counter_reset : 1; + uint64_t ppt_cycle_counter_scaler : 3; + uint64_t ppt_squash_timer_match_val : 6; + uint64_t ppt_timer_timeout_enable : 1; + uint64_t ppt_lpar_change_enable : 1; + uint64_t ppt_global_actual_change_enable : 1; + uint64_t ppt_local_voltage_change_enable : 1; + uint64_t ppt_ivrm_bypass_change_enable : 1; + uint64_t ppt_idle_entry_enable : 1; + uint64_t ppt_idle_exit_enable : 1; + uint64_t ppt_timer_timeout_priority : 1; + uint64_t ppt_lpar_change_priority : 1; + uint64_t ppt_global_actual_change_priority : 1; + uint64_t ppt_local_voltage_change_priority : 1; + uint64_t ppt_ivrm_bypass_change_priority : 1; + uint64_t ppt_idle_entry_priority : 1; + uint64_t ppt_idle_exit_priority : 1; + uint64_t ppt_legacy_mode : 1; + uint64_t _reserved0 : 1; +#else + uint64_t _reserved0 : 1; + uint64_t ppt_legacy_mode : 1; + uint64_t ppt_idle_exit_priority : 1; + uint64_t ppt_idle_entry_priority : 1; + uint64_t ppt_ivrm_bypass_change_priority : 1; + uint64_t ppt_local_voltage_change_priority : 1; + uint64_t ppt_global_actual_change_priority : 1; + uint64_t ppt_lpar_change_priority : 1; + uint64_t ppt_timer_timeout_priority : 1; + uint64_t ppt_idle_exit_enable : 1; + uint64_t ppt_idle_entry_enable : 1; + uint64_t ppt_ivrm_bypass_change_enable : 1; + uint64_t ppt_local_voltage_change_enable : 1; + uint64_t ppt_global_actual_change_enable : 1; + uint64_t ppt_lpar_change_enable : 1; + uint64_t ppt_timer_timeout_enable : 1; + uint64_t ppt_squash_timer_match_val : 6; + uint64_t ppt_cycle_counter_scaler : 3; + uint64_t disable_ppt_cycle_counter_reset : 1; + uint64_t ppt_int_timer_select : 2; + uint64_t disable_ppt_int_timer_reset : 1; + uint64_t ppt_trace_timer_match_val : 11; + uint64_t avg_freq_counter_scaler : 3; + uint64_t memory_activity_range_select : 4; + uint64_t power_proxy_activity_range_select_vdd : 5; + uint64_t power_proxy_activity_range_select_vcs : 5; + uint64_t disable_activity_proxy_reset : 1; + uint64_t core_activity_sample_enable : 1; + uint64_t activity_sample_l2l3_enable : 1; + uint64_t l3_act_count_is_free_running : 1; + uint64_t l2_act_count_is_free_running : 1; + uint64_t enable_ppt_trace : 1; + uint64_t enable_activity_sampling : 1; +#endif // _BIG_ENDIAN + } fields; +} oha_activity_sample_mode_reg_t; + + + +typedef union oha_vcs_activity_cnt_reg { + + 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 l2_activity_count_24bit_vcs : 24; + uint64_t l3_activity_count_24bit_vcs : 24; + uint64_t _reserved0 : 16; +#else + uint64_t _reserved0 : 16; + uint64_t l3_activity_count_24bit_vcs : 24; + uint64_t l2_activity_count_24bit_vcs : 24; +#endif // _BIG_ENDIAN + } fields; +} oha_vcs_activity_cnt_reg_t; + + + +typedef union oha_vdd_activity_cnt_reg { + + 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 l2_activity_count_24bit_vdd : 24; + uint64_t l3_activity_count_24bit_vdd : 24; + uint64_t _reserved0 : 16; +#else + uint64_t _reserved0 : 16; + uint64_t l3_activity_count_24bit_vdd : 24; + uint64_t l2_activity_count_24bit_vdd : 24; +#endif // _BIG_ENDIAN + } fields; +} oha_vdd_activity_cnt_reg_t; + + + +typedef union oha_low_activity_detect_mode_reg { + + 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 low_activity_detect_sample_enable : 1; + uint64_t low_activity_detect_timer_select_for_entry : 8; + uint64_t low_activity_detect_timer_select_for_exit : 8; + uint64_t low_activity_detect_threshold_range : 4; + uint64_t low_activity_detect_threshold_entry : 16; + uint64_t low_activity_detect_threshold_exit : 16; + uint64_t _reserved0 : 11; +#else + uint64_t _reserved0 : 11; + uint64_t low_activity_detect_threshold_exit : 16; + uint64_t low_activity_detect_threshold_entry : 16; + uint64_t low_activity_detect_threshold_range : 4; + uint64_t low_activity_detect_timer_select_for_exit : 8; + uint64_t low_activity_detect_timer_select_for_entry : 8; + uint64_t low_activity_detect_sample_enable : 1; +#endif // _BIG_ENDIAN + } fields; +} oha_low_activity_detect_mode_reg_t; + + + +typedef union oha_activity_and_frequ_reg { + + 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 low_activity_detect_engaged : 1; + uint64_t _reserved0 : 63; +#else + uint64_t _reserved0 : 63; + uint64_t low_activity_detect_engaged : 1; +#endif // _BIG_ENDIAN + } fields; +} oha_activity_and_frequ_reg_t; + + + +typedef union oha_counter_reg { + + 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 base_counter : 16; + uint64_t idle_detec_timer : 16; + uint64_t tod_count_msbs : 16; + uint64_t ppt_cycle_count_ovfl : 1; + uint64_t ppt_parity_error : 1; + uint64_t _reserved0 : 14; +#else + uint64_t _reserved0 : 14; + uint64_t ppt_parity_error : 1; + uint64_t ppt_cycle_count_ovfl : 1; + uint64_t tod_count_msbs : 16; + uint64_t idle_detec_timer : 16; + uint64_t base_counter : 16; +#endif // _BIG_ENDIAN + } fields; +} oha_counter_reg_t; + + + +typedef union oha_proxy_reg { + + 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 average_frequency : 32; + uint64_t special_memory_activity_cnt : 24; + uint64_t _reserved0 : 8; +#else + uint64_t _reserved0 : 8; + uint64_t special_memory_activity_cnt : 24; + uint64_t average_frequency : 32; +#endif // _BIG_ENDIAN + } fields; +} oha_proxy_reg_t; + + + +typedef union oha_proxy_legacy_reg { + + 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 aproxy_vdd : 16; + uint64_t aproxy_vcs : 16; + uint64_t memory_activity_cnt : 16; + uint64_t scaled_average_frequency : 16; +#else + uint64_t scaled_average_frequency : 16; + uint64_t memory_activity_cnt : 16; + uint64_t aproxy_vcs : 16; + uint64_t aproxy_vdd : 16; +#endif // _BIG_ENDIAN + } fields; +} oha_proxy_legacy_reg_t; + + + +typedef union oha_skitter_ctrl_mode_reg { + + 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 start_skitter_mux_sel : 3; + uint64_t stop_skitter_mux_sel : 3; + uint64_t skitter_timer_start_mux_sel : 3; + uint64_t disable_skitter_qualification_mode : 1; + uint64_t skitter_timer_enable_freerun_mode : 1; + uint64_t skitter_timer_range_select : 4; + uint64_t _reserved0 : 49; +#else + uint64_t _reserved0 : 49; + uint64_t skitter_timer_range_select : 4; + uint64_t skitter_timer_enable_freerun_mode : 1; + uint64_t disable_skitter_qualification_mode : 1; + uint64_t skitter_timer_start_mux_sel : 3; + uint64_t stop_skitter_mux_sel : 3; + uint64_t start_skitter_mux_sel : 3; +#endif // _BIG_ENDIAN + } fields; +} oha_skitter_ctrl_mode_reg_t; + + + +typedef union oha_cpm_ctrl_reg { + + 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 cpm_bit_sel : 2; + uint64_t cpm_bit_sel_trig_0 : 3; + uint64_t cpm_bit_sel_trig_1 : 3; + uint64_t scom_marker : 8; + uint64_t cpm_mark_select : 2; + uint64_t cpm_htm_mode : 1; + uint64_t cpm_scom_mask : 8; + uint64_t cpm_scom_mode : 2; + uint64_t cpm_data_mode : 1; + uint64_t _reserved0 : 34; +#else + uint64_t _reserved0 : 34; + uint64_t cpm_data_mode : 1; + uint64_t cpm_scom_mode : 2; + uint64_t cpm_scom_mask : 8; + uint64_t cpm_htm_mode : 1; + uint64_t cpm_mark_select : 2; + uint64_t scom_marker : 8; + uint64_t cpm_bit_sel_trig_1 : 3; + uint64_t cpm_bit_sel_trig_0 : 3; + uint64_t cpm_bit_sel : 2; +#endif // _BIG_ENDIAN + } fields; +} oha_cpm_ctrl_reg_t; + + + +typedef union oha_cpm_hist_reset_reg { + + 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 hist_reset : 1; + uint64_t pconly_special_wakeup : 1; + uint64_t _reserved0 : 62; +#else + uint64_t _reserved0 : 62; + uint64_t pconly_special_wakeup : 1; + uint64_t hist_reset : 1; +#endif // _BIG_ENDIAN + } fields; +} oha_cpm_hist_reset_reg_t; + +#endif // __ASSEMBLER__ +#define OHA_CPM_HIST_RESET_REG_HIST_RESET SIXTYFOUR_BIT_CONSTANT(0x8000000000000000) +#define OHA_CPM_HIST_RESET_REG_PCONLY_SPECIAL_WAKEUP SIXTYFOUR_BIT_CONSTANT(0x4000000000000000) +#ifndef __ASSEMBLER__ + + +typedef union oha_ro_status_reg { + + 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 low_activity_detect_bit : 1; + uint64_t special_wakeup_completed : 1; + uint64_t architected_idle_state_from_core : 3; + uint64_t core_access_impossible : 1; + uint64_t eco_access_impossible : 1; + uint64_t spare_6bit : 6; + uint64_t current_aiss_fsm_state_vector : 7; + uint64_t eff_idle_state : 3; + uint64_t spare_1bit : 1; + uint64_t pc_tc_deep_idle_thread_state : 8; + uint64_t lpar_id : 12; + uint64_t ppt_fsm_l : 4; + uint64_t _reserved0 : 16; +#else + uint64_t _reserved0 : 16; + uint64_t ppt_fsm_l : 4; + uint64_t lpar_id : 12; + uint64_t pc_tc_deep_idle_thread_state : 8; + uint64_t spare_1bit : 1; + uint64_t eff_idle_state : 3; + uint64_t current_aiss_fsm_state_vector : 7; + uint64_t spare_6bit : 6; + uint64_t eco_access_impossible : 1; + uint64_t core_access_impossible : 1; + uint64_t architected_idle_state_from_core : 3; + uint64_t special_wakeup_completed : 1; + uint64_t low_activity_detect_bit : 1; +#endif // _BIG_ENDIAN + } fields; +} oha_ro_status_reg_t; + +#endif // __ASSEMBLER__ +#define OHA_RO_STATUS_REG_LOW_ACTIVITY_DETECT_BIT SIXTYFOUR_BIT_CONSTANT(0x8000000000000000) +#define OHA_RO_STATUS_REG_SPECIAL_WAKEUP_COMPLETED SIXTYFOUR_BIT_CONSTANT(0x4000000000000000) +#define OHA_RO_STATUS_REG_ARCHITECTED_IDLE_STATE_FROM_CORE_MASK SIXTYFOUR_BIT_CONSTANT(0x3800000000000000) +#define OHA_RO_STATUS_REG_CORE_ACCESS_IMPOSSIBLE SIXTYFOUR_BIT_CONSTANT(0x0400000000000000) +#define OHA_RO_STATUS_REG_ECO_ACCESS_IMPOSSIBLE SIXTYFOUR_BIT_CONSTANT(0x0200000000000000) +#define OHA_RO_STATUS_REG_SPARE_6BIT_MASK SIXTYFOUR_BIT_CONSTANT(0x01f8000000000000) +#define OHA_RO_STATUS_REG_CURRENT_AISS_FSM_STATE_VECTOR_MASK SIXTYFOUR_BIT_CONSTANT(0x0007f00000000000) +#define OHA_RO_STATUS_REG_EFF_IDLE_STATE_MASK SIXTYFOUR_BIT_CONSTANT(0x00000e0000000000) +#define OHA_RO_STATUS_REG_SPARE_1BIT SIXTYFOUR_BIT_CONSTANT(0x0000010000000000) +#define OHA_RO_STATUS_REG_PC_TC_DEEP_IDLE_THREAD_STATE_MASK SIXTYFOUR_BIT_CONSTANT(0x000000ff00000000) +#define OHA_RO_STATUS_REG_LPAR_ID_MASK SIXTYFOUR_BIT_CONSTANT(0x00000000fff00000) +#define OHA_RO_STATUS_REG_PPT_FSM_L_MASK SIXTYFOUR_BIT_CONSTANT(0x00000000000f0000) +#ifndef __ASSEMBLER__ + + +typedef union oha_mode_reg { + + 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 enable_ignore_recov_errors : 1; + uint64_t enable_arch_idle_mode_sequencer : 1; + uint64_t treat_sleep_as_nap : 1; + uint64_t treat_winkle_as_sleep : 1; + uint64_t enable_pstate_tracing : 1; + uint64_t enable_suppress_purges_and_pcb_fence : 1; + uint64_t idle_state_override_en : 1; + uint64_t idle_state_override_value : 3; + uint64_t disable_aiss_core_handshake : 1; + uint64_t aiss_hang_detect_timer_sel : 4; + uint64_t enable_l2_purge_abort : 1; + uint64_t enable_l3_purge_abort : 1; + uint64_t tod_pulse_count_match_val : 14; + uint64_t trace_debug_mode_select : 2; + uint64_t lpft_mode : 1; + uint64_t _reserved0 : 30; +#else + uint64_t _reserved0 : 30; + uint64_t lpft_mode : 1; + uint64_t trace_debug_mode_select : 2; + uint64_t tod_pulse_count_match_val : 14; + uint64_t enable_l3_purge_abort : 1; + uint64_t enable_l2_purge_abort : 1; + uint64_t aiss_hang_detect_timer_sel : 4; + uint64_t disable_aiss_core_handshake : 1; + uint64_t idle_state_override_value : 3; + uint64_t idle_state_override_en : 1; + uint64_t enable_suppress_purges_and_pcb_fence : 1; + uint64_t enable_pstate_tracing : 1; + uint64_t treat_winkle_as_sleep : 1; + uint64_t treat_sleep_as_nap : 1; + uint64_t enable_arch_idle_mode_sequencer : 1; + uint64_t enable_ignore_recov_errors : 1; +#endif // _BIG_ENDIAN + } fields; +} oha_mode_reg_t; + + + +typedef union oha_error_and_error_mask_reg { + + 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 oha_error_mask : 8; + uint64_t oha_chiplet_errors : 8; + uint64_t _reserved0 : 48; +#else + uint64_t _reserved0 : 48; + uint64_t oha_chiplet_errors : 8; + uint64_t oha_error_mask : 8; +#endif // _BIG_ENDIAN + } fields; +} oha_error_and_error_mask_reg_t; + + + +typedef union oha_arch_idle_state_reg { + + 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 aiss_thold_sequence_select : 1; + uint64_t disable_waiting_on_l3 : 1; + uint64_t idle_seq_timer_select : 2; + uint64_t allow_aiss_interrupts : 1; + uint64_t enable_reset_of_counters_while_sleepwinkle : 1; + uint64_t select_p7p_seq_wait_time : 1; + uint64_t disable_auto_sleep_entry : 1; + uint64_t disable_auto_winkle_entry : 1; + uint64_t reset_idle_state_sequencer : 1; + uint64_t _reserved0 : 54; +#else + uint64_t _reserved0 : 54; + uint64_t reset_idle_state_sequencer : 1; + uint64_t disable_auto_winkle_entry : 1; + uint64_t disable_auto_sleep_entry : 1; + uint64_t select_p7p_seq_wait_time : 1; + uint64_t enable_reset_of_counters_while_sleepwinkle : 1; + uint64_t allow_aiss_interrupts : 1; + uint64_t idle_seq_timer_select : 2; + uint64_t disable_waiting_on_l3 : 1; + uint64_t aiss_thold_sequence_select : 1; +#endif // _BIG_ENDIAN + } fields; +} oha_arch_idle_state_reg_t; + + + +typedef union oha_pmu_config_reg { + + 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 pmu_pstate_threshold_a : 8; + uint64_t pmu_pstate_threshold_b : 8; + uint64_t pmu_configuration : 3; + uint64_t _reserved0 : 45; +#else + uint64_t _reserved0 : 45; + uint64_t pmu_configuration : 3; + uint64_t pmu_pstate_threshold_b : 8; + uint64_t pmu_pstate_threshold_a : 8; +#endif // _BIG_ENDIAN + } fields; +} oha_pmu_config_reg_t; + + + +typedef union oha_aiss_io_reg { + + 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 spare_2bits_b : 2; + uint64_t tc_tp_chiplet_pm_state : 4; + uint64_t tc_pb_sleep : 1; + uint64_t tc_tc_pm_thold_ctrl : 3; + uint64_t tc_l3_fence_lco : 1; + uint64_t tc_ncu_fence : 1; + uint64_t chksw_hw237039dis : 1; + uint64_t tc_l3_init_dram : 1; + uint64_t tc_pb_purge : 1; + uint64_t tc_pc_pm_wake_up : 1; + uint64_t spare_entry_for_config_bit : 1; + uint64_t reset_of_counters_while_sleepwinkle : 1; + uint64_t tc_chtm_purge : 1; + uint64_t tc_tp_terminate_pcb : 1; + uint64_t tc_oha_therm_purge_lvl : 1; + uint64_t pscom_core_fence_lvl : 1; + uint64_t pb_eco_fence_lvl : 1; + uint64_t core2cache_fence_req : 1; + uint64_t cache2core_fence_req : 1; + uint64_t pervasive_eco_fence_req : 1; + uint64_t tc_oha_pmx_fence_req_lvl_l : 1; + uint64_t updateohafreq : 1; + uint64_t req_idle_state_change : 1; + uint64_t tc_l2_purge : 1; + uint64_t tc_l3_purge : 1; + uint64_t tc_ncu_purge : 1; + uint64_t tc_l2_purge_abort : 1; + uint64_t tc_l3_purge_abort : 1; + uint64_t pc_tc_pm_state : 3; + uint64_t l2_purge_is_done : 1; + uint64_t l3_ncu_chtm_purge_done : 3; + uint64_t tc_tc_xstop_err : 1; + uint64_t tc_tc_recov_err : 1; + uint64_t pb_tc_purge_active_lvl : 1; + uint64_t l3_tc_dram_ready_lvl : 1; + uint64_t core_fsm_non_idle : 1; + uint64_t tc_pscom_core_fence_done : 1; + uint64_t tc_pmx_oha_fence_done : 1; + uint64_t l2_purge_abort_sticky : 1; + uint64_t l3_purge_abort_sticky : 1; + uint64_t _reserved0 : 14; +#else + uint64_t _reserved0 : 14; + uint64_t l3_purge_abort_sticky : 1; + uint64_t l2_purge_abort_sticky : 1; + uint64_t tc_pmx_oha_fence_done : 1; + uint64_t tc_pscom_core_fence_done : 1; + uint64_t core_fsm_non_idle : 1; + uint64_t l3_tc_dram_ready_lvl : 1; + uint64_t pb_tc_purge_active_lvl : 1; + uint64_t tc_tc_recov_err : 1; + uint64_t tc_tc_xstop_err : 1; + uint64_t l3_ncu_chtm_purge_done : 3; + uint64_t l2_purge_is_done : 1; + uint64_t pc_tc_pm_state : 3; + uint64_t tc_l3_purge_abort : 1; + uint64_t tc_l2_purge_abort : 1; + uint64_t tc_ncu_purge : 1; + uint64_t tc_l3_purge : 1; + uint64_t tc_l2_purge : 1; + uint64_t req_idle_state_change : 1; + uint64_t updateohafreq : 1; + uint64_t tc_oha_pmx_fence_req_lvl_l : 1; + uint64_t pervasive_eco_fence_req : 1; + uint64_t cache2core_fence_req : 1; + uint64_t core2cache_fence_req : 1; + uint64_t pb_eco_fence_lvl : 1; + uint64_t pscom_core_fence_lvl : 1; + uint64_t tc_oha_therm_purge_lvl : 1; + uint64_t tc_tp_terminate_pcb : 1; + uint64_t tc_chtm_purge : 1; + uint64_t reset_of_counters_while_sleepwinkle : 1; + uint64_t spare_entry_for_config_bit : 1; + uint64_t tc_pc_pm_wake_up : 1; + uint64_t tc_pb_purge : 1; + uint64_t tc_l3_init_dram : 1; + uint64_t chksw_hw237039dis : 1; + uint64_t tc_ncu_fence : 1; + uint64_t tc_l3_fence_lco : 1; + uint64_t tc_tc_pm_thold_ctrl : 3; + uint64_t tc_pb_sleep : 1; + uint64_t tc_tp_chiplet_pm_state : 4; + uint64_t spare_2bits_b : 2; +#endif // _BIG_ENDIAN + } fields; +} oha_aiss_io_reg_t; + + + +typedef union oha_ppt_bar_reg { + + 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 ppt_bar : 46; + uint64_t ppt_size_mask : 7; + uint64_t ppt_address_scope : 3; + uint64_t _reserved0 : 8; +#else + uint64_t _reserved0 : 8; + uint64_t ppt_address_scope : 3; + uint64_t ppt_size_mask : 7; + uint64_t ppt_bar : 46; +#endif // _BIG_ENDIAN + } fields; +} oha_ppt_bar_reg_t; + + + +typedef union oha_l2_vcs_directory_read_weight { + + 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 : 6; + uint64_t _reserved0 : 58; +#else + uint64_t _reserved0 : 58; + uint64_t value : 6; +#endif // _BIG_ENDIAN + } fields; +} oha_l2_vcs_directory_read_weight_t; + + + +typedef union oha_l2_vcs_directory_write_weight { + + 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 : 6; + uint64_t _reserved0 : 58; +#else + uint64_t _reserved0 : 58; + uint64_t value : 6; +#endif // _BIG_ENDIAN + } fields; +} oha_l2_vcs_directory_write_weight_t; + + + +typedef union oha_l2_vcs_cache_full_read_weight { + + 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 : 6; + uint64_t _reserved0 : 58; +#else + uint64_t _reserved0 : 58; + uint64_t value : 6; +#endif // _BIG_ENDIAN + } fields; +} oha_l2_vcs_cache_full_read_weight_t; + + + +typedef union oha_l2_vcs_cache_targeted_read_weight { + + 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 : 6; + uint64_t _reserved0 : 58; +#else + uint64_t _reserved0 : 58; + uint64_t value : 6; +#endif // _BIG_ENDIAN + } fields; +} oha_l2_vcs_cache_targeted_read_weight_t; + + + +typedef union oha_l2_vcs_cache_write_cnt_weight { + + 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 : 6; + uint64_t _reserved0 : 58; +#else + uint64_t _reserved0 : 58; + uint64_t value : 6; +#endif // _BIG_ENDIAN + } fields; +} oha_l2_vcs_cache_write_cnt_weight_t; + + + +typedef union oha_l3_vcs_directory_read_weight { + + 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 : 6; + uint64_t _reserved0 : 58; +#else + uint64_t _reserved0 : 58; + uint64_t value : 6; +#endif // _BIG_ENDIAN + } fields; +} oha_l3_vcs_directory_read_weight_t; + + + +typedef union oha_l3_vcs_directory_write_weight { + + 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 : 6; + uint64_t _reserved0 : 58; +#else + uint64_t _reserved0 : 58; + uint64_t value : 6; +#endif // _BIG_ENDIAN + } fields; +} oha_l3_vcs_directory_write_weight_t; + + + +typedef union oha_l3_vcs_cache_access_weight { + + 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 : 6; + uint64_t _reserved0 : 58; +#else + uint64_t _reserved0 : 58; + uint64_t value : 6; +#endif // _BIG_ENDIAN + } fields; +} oha_l3_vcs_cache_access_weight_t; + + + +typedef union oha_l2_vdd_directory_read_weight { + + 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 : 6; + uint64_t _reserved0 : 58; +#else + uint64_t _reserved0 : 58; + uint64_t value : 6; +#endif // _BIG_ENDIAN + } fields; +} oha_l2_vdd_directory_read_weight_t; + + + +typedef union oha_l2_vdd_directory_write_weight { + + 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 : 6; + uint64_t _reserved0 : 58; +#else + uint64_t _reserved0 : 58; + uint64_t value : 6; +#endif // _BIG_ENDIAN + } fields; +} oha_l2_vdd_directory_write_weight_t; + + + +typedef union oha_l2_vdd_cache_full_read_weight { + + 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 : 6; + uint64_t _reserved0 : 58; +#else + uint64_t _reserved0 : 58; + uint64_t value : 6; +#endif // _BIG_ENDIAN + } fields; +} oha_l2_vdd_cache_full_read_weight_t; + + + +typedef union oha_l2_vdd_cache_targeted_read_weight { + + 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 : 6; + uint64_t _reserved0 : 58; +#else + uint64_t _reserved0 : 58; + uint64_t value : 6; +#endif // _BIG_ENDIAN + } fields; +} oha_l2_vdd_cache_targeted_read_weight_t; + + + +typedef union oha_l2_vdd_cache_write_cnt_weight { + + 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 : 6; + uint64_t _reserved0 : 58; +#else + uint64_t _reserved0 : 58; + uint64_t value : 6; +#endif // _BIG_ENDIAN + } fields; +} oha_l2_vdd_cache_write_cnt_weight_t; + + + +typedef union oha_l3_vdd_directory_read_weight { + + 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 : 6; + uint64_t _reserved0 : 58; +#else + uint64_t _reserved0 : 58; + uint64_t value : 6; +#endif // _BIG_ENDIAN + } fields; +} oha_l3_vdd_directory_read_weight_t; + + + +typedef union oha_l3_vdd_directory_write_weight { + + 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 : 6; + uint64_t _reserved0 : 58; +#else + uint64_t _reserved0 : 58; + uint64_t value : 6; +#endif // _BIG_ENDIAN + } fields; +} oha_l3_vdd_directory_write_weight_t; + + + +typedef union oha_l3_vdd_cache_access_weight { + + 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 : 6; + uint64_t _reserved0 : 58; +#else + uint64_t _reserved0 : 58; + uint64_t value : 6; +#endif // _BIG_ENDIAN + } fields; +} oha_l3_vdd_cache_access_weight_t; + + + +typedef union oha_chksw_hw132623dis { + + 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 : 1; + uint64_t _reserved0 : 63; +#else + uint64_t _reserved0 : 63; + uint64_t value : 1; +#endif // _BIG_ENDIAN + } fields; +} oha_chksw_hw132623dis_t; + + + +typedef union oha_activity_scale_factor_array { + + 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 : 56; + uint64_t _reserved0 : 8; +#else + uint64_t _reserved0 : 8; + uint64_t value : 56; +#endif // _BIG_ENDIAN + } fields; +} oha_activity_scale_factor_array_t; + + + +typedef union oha_activity_scale_shift_factor_array { + + 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 : 42; + uint64_t _reserved0 : 22; +#else + uint64_t _reserved0 : 22; + uint64_t value : 42; +#endif // _BIG_ENDIAN + } fields; +} oha_activity_scale_shift_factor_array_t; + + +#endif // __ASSEMBLER__ +#endif // __OHA_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/oha_register_addresses.h b/src/ssx/pgp/registers/oha_register_addresses.h new file mode 100755 index 0000000..1f07b37 --- /dev/null +++ b/src/ssx/pgp/registers/oha_register_addresses.h @@ -0,0 +1,39 @@ +#ifndef __OHA_REGISTER_ADDRESSES_H__ +#define __OHA_REGISTER_ADDRESSES_H__ + +// $Id: oha_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/oha_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file oha_register_addresses.h +/// \brief Symbolic addresses for the OHA unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define OHA_PCB_BASE 0x10020000 +#define OHA_ACTIVITY_SAMPLE_MODE_REG 0x10020000 +#define OHA_VCS_ACTIVITY_CNT_REG 0x10020001 +#define OHA_VDD_ACTIVITY_CNT_REG 0x10020002 +#define OHA_LOW_ACTIVITY_DETECT_MODE_REG 0x10020003 +#define OHA_ACTIVITY_AND_FREQU_REG 0x10020004 +#define OHA_COUNTER_REG 0x10020005 +#define OHA_PROXY_REG 0x10020006 +#define OHA_PROXY_LEGACY_REG 0x10020007 +#define OHA_SKITTER_CTRL_MODE_REG 0x10020008 +#define OHA_CPM_CTRL_REG 0x1002000a +#define OHA_CPM_HIST_RESET_REG 0x10020013 +#define OHA_RO_STATUS_REG 0x1002000b +#define OHA_MODE_REG 0x1002000d +#define OHA_ERROR_AND_ERROR_MASK_REG 0x1002000e +#define OHA_ARCH_IDLE_STATE_REG 0x10020011 +#define OHA_PMU_CONFIG_REG 0x10020012 +#define OHA_AISS_IO_REG 0x10020014 +#define OHA_PPT_BAR_REG 0x10020015 + +#endif // __OHA_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/pba_firmware_registers.h b/src/ssx/pgp/registers/pba_firmware_registers.h new file mode 100755 index 0000000..502ef51 --- /dev/null +++ b/src/ssx/pgp/registers/pba_firmware_registers.h @@ -0,0 +1,2184 @@ +#ifndef __PBA_FIRMWARE_REGISTERS_H__ +#define __PBA_FIRMWARE_REGISTERS_H__ + +// $Id: pba_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pba_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pba_firmware_registers.h +/// \brief C register structs for the PBA unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union pba_barn { + + 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 cmd_scope : 3; + uint64_t reserved0 : 1; + uint64_t reserved1 : 10; + uint64_t addr : 30; + uint64_t _reserved0 : 20; +#else + uint64_t _reserved0 : 20; + uint64_t addr : 30; + uint64_t reserved1 : 10; + uint64_t reserved0 : 1; + uint64_t cmd_scope : 3; +#endif // _BIG_ENDIAN + } fields; +} pba_barn_t; + +#endif // __ASSEMBLER__ +#define PBA_BARN_CMD_SCOPE_MASK SIXTYFOUR_BIT_CONSTANT(0xe000000000000000) +#define PBA_BARN_ADDR_MASK SIXTYFOUR_BIT_CONSTANT(0x0003fffffff00000) +#ifndef __ASSEMBLER__ + + +typedef union pba_barmskn { + + 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 reserved0 : 23; + uint64_t mask : 21; + uint64_t _reserved0 : 20; +#else + uint64_t _reserved0 : 20; + uint64_t mask : 21; + uint64_t reserved0 : 23; +#endif // _BIG_ENDIAN + } fields; +} pba_barmskn_t; + +#endif // __ASSEMBLER__ +#define PBA_BARMSKN_MASK_MASK SIXTYFOUR_BIT_CONSTANT(0x000001fffff00000) +#ifndef __ASSEMBLER__ + + +typedef union pba_fir { + + 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 oci_apar_err : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_ce_fw : 1; + uint64_t oci_slave_init : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_rereqto : 1; + uint64_t pb_unexpcresp : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_crespto : 1; + uint64_t bcue_setup_err : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t internal_err : 1; + uint64_t illegal_cache_op : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t axpush_wrerr : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axflow_err : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_rsverr : 1; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t reserved41 : 3; + uint64_t fir_parity_err2 : 1; + uint64_t fir_parity_err : 1; + uint64_t _reserved0 : 18; +#else + uint64_t _reserved0 : 18; + uint64_t fir_parity_err : 1; + uint64_t fir_parity_err2 : 1; + uint64_t reserved41 : 3; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t axsnd_rsverr : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axflow_err : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axpush_wrerr : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t illegal_cache_op : 1; + uint64_t internal_err : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_setup_err : 1; + uint64_t pb_crespto : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_unexpcresp : 1; + uint64_t oci_rereqto : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_slave_init : 1; + uint64_t pb_ce_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t oci_apar_err : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_fir_t; + +#endif // __ASSEMBLER__ +#define PBA_FIR_OCI_APAR_ERR SIXTYFOUR_BIT_CONSTANT(0x8000000000000000) +#define PBA_FIR_PB_RDADRERR_FW SIXTYFOUR_BIT_CONSTANT(0x4000000000000000) +#define PBA_FIR_PB_RDDATATO_FW SIXTYFOUR_BIT_CONSTANT(0x2000000000000000) +#define PBA_FIR_PB_SUE_FW SIXTYFOUR_BIT_CONSTANT(0x1000000000000000) +#define PBA_FIR_PB_UE_FW SIXTYFOUR_BIT_CONSTANT(0x0800000000000000) +#define PBA_FIR_PB_CE_FW SIXTYFOUR_BIT_CONSTANT(0x0400000000000000) +#define PBA_FIR_OCI_SLAVE_INIT SIXTYFOUR_BIT_CONSTANT(0x0200000000000000) +#define PBA_FIR_OCI_WRPAR_ERR SIXTYFOUR_BIT_CONSTANT(0x0100000000000000) +#define PBA_FIR_OCI_REREQTO SIXTYFOUR_BIT_CONSTANT(0x0080000000000000) +#define PBA_FIR_PB_UNEXPCRESP SIXTYFOUR_BIT_CONSTANT(0x0040000000000000) +#define PBA_FIR_PB_UNEXPDATA SIXTYFOUR_BIT_CONSTANT(0x0020000000000000) +#define PBA_FIR_PB_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0010000000000000) +#define PBA_FIR_PB_WRADRERR_FW SIXTYFOUR_BIT_CONSTANT(0x0008000000000000) +#define PBA_FIR_PB_BADCRESP SIXTYFOUR_BIT_CONSTANT(0x0004000000000000) +#define PBA_FIR_PB_ACKDEAD_FW SIXTYFOUR_BIT_CONSTANT(0x0002000000000000) +#define PBA_FIR_PB_CRESPTO SIXTYFOUR_BIT_CONSTANT(0x0001000000000000) +#define PBA_FIR_BCUE_SETUP_ERR SIXTYFOUR_BIT_CONSTANT(0x0000800000000000) +#define PBA_FIR_BCUE_PB_ACK_DEAD SIXTYFOUR_BIT_CONSTANT(0x0000400000000000) +#define PBA_FIR_BCUE_PB_ADRERR SIXTYFOUR_BIT_CONSTANT(0x0000200000000000) +#define PBA_FIR_BCUE_OCI_DATAERR SIXTYFOUR_BIT_CONSTANT(0x0000100000000000) +#define PBA_FIR_BCDE_SETUP_ERR SIXTYFOUR_BIT_CONSTANT(0x0000080000000000) +#define PBA_FIR_BCDE_PB_ACK_DEAD SIXTYFOUR_BIT_CONSTANT(0x0000040000000000) +#define PBA_FIR_BCDE_PB_ADRERR SIXTYFOUR_BIT_CONSTANT(0x0000020000000000) +#define PBA_FIR_BCDE_RDDATATO_ERR SIXTYFOUR_BIT_CONSTANT(0x0000010000000000) +#define PBA_FIR_BCDE_SUE_ERR SIXTYFOUR_BIT_CONSTANT(0x0000008000000000) +#define PBA_FIR_BCDE_UE_ERR SIXTYFOUR_BIT_CONSTANT(0x0000004000000000) +#define PBA_FIR_BCDE_CE SIXTYFOUR_BIT_CONSTANT(0x0000002000000000) +#define PBA_FIR_BCDE_OCI_DATAERR SIXTYFOUR_BIT_CONSTANT(0x0000001000000000) +#define PBA_FIR_INTERNAL_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000800000000) +#define PBA_FIR_ILLEGAL_CACHE_OP SIXTYFOUR_BIT_CONSTANT(0x0000000400000000) +#define PBA_FIR_OCI_BAD_REG_ADDR SIXTYFOUR_BIT_CONSTANT(0x0000000200000000) +#define PBA_FIR_AXPUSH_WRERR SIXTYFOUR_BIT_CONSTANT(0x0000000100000000) +#define PBA_FIR_AXRCV_DLO_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000080000000) +#define PBA_FIR_AXRCV_DLO_TO SIXTYFOUR_BIT_CONSTANT(0x0000000040000000) +#define PBA_FIR_AXRCV_RSVDATA_TO SIXTYFOUR_BIT_CONSTANT(0x0000000020000000) +#define PBA_FIR_AXFLOW_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000010000000) +#define PBA_FIR_AXSND_DHI_RTYTO SIXTYFOUR_BIT_CONSTANT(0x0000000008000000) +#define PBA_FIR_AXSND_DLO_RTYTO SIXTYFOUR_BIT_CONSTANT(0x0000000004000000) +#define PBA_FIR_AXSND_RSVTO SIXTYFOUR_BIT_CONSTANT(0x0000000002000000) +#define PBA_FIR_AXSND_RSVERR SIXTYFOUR_BIT_CONSTANT(0x0000000001000000) +#define PBA_FIR_PB_ACKDEAD_FW_WR SIXTYFOUR_BIT_CONSTANT(0x0000000000800000) +#define PBA_FIR_FIR_PARITY_ERR2 SIXTYFOUR_BIT_CONSTANT(0x0000000000080000) +#define PBA_FIR_FIR_PARITY_ERR SIXTYFOUR_BIT_CONSTANT(0x0000000000040000) +#ifndef __ASSEMBLER__ + + +typedef union pba_fir_and { + + 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 oci_apar_err : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_ce_fw : 1; + uint64_t oci_slave_init : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_rereqto : 1; + uint64_t pb_unexpcresp : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_crespto : 1; + uint64_t bcue_setup_err : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t internal_err : 1; + uint64_t illegal_cache_op : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t axpush_wrerr : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axflow_err : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_rsverr : 1; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t reserved41 : 3; + uint64_t fir_parity_err2 : 1; + uint64_t fir_parity_err : 1; + uint64_t _reserved0 : 18; +#else + uint64_t _reserved0 : 18; + uint64_t fir_parity_err : 1; + uint64_t fir_parity_err2 : 1; + uint64_t reserved41 : 3; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t axsnd_rsverr : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axflow_err : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axpush_wrerr : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t illegal_cache_op : 1; + uint64_t internal_err : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_setup_err : 1; + uint64_t pb_crespto : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_unexpcresp : 1; + uint64_t oci_rereqto : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_slave_init : 1; + uint64_t pb_ce_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t oci_apar_err : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_fir_and_t; + + + +typedef union pba_fir_or { + + 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 oci_apar_err : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_ce_fw : 1; + uint64_t oci_slave_init : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_rereqto : 1; + uint64_t pb_unexpcresp : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_crespto : 1; + uint64_t bcue_setup_err : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t internal_err : 1; + uint64_t illegal_cache_op : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t axpush_wrerr : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axflow_err : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_rsverr : 1; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t reserved41 : 3; + uint64_t fir_parity_err2 : 1; + uint64_t fir_parity_err : 1; + uint64_t _reserved0 : 18; +#else + uint64_t _reserved0 : 18; + uint64_t fir_parity_err : 1; + uint64_t fir_parity_err2 : 1; + uint64_t reserved41 : 3; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t axsnd_rsverr : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axflow_err : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axpush_wrerr : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t illegal_cache_op : 1; + uint64_t internal_err : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_setup_err : 1; + uint64_t pb_crespto : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_unexpcresp : 1; + uint64_t oci_rereqto : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_slave_init : 1; + uint64_t pb_ce_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t oci_apar_err : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_fir_or_t; + + + +typedef union pba_firmask { + + 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 oci_apar_err : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_ce_fw : 1; + uint64_t oci_slave_init : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_rereqto : 1; + uint64_t pb_unexpcresp : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_crespto : 1; + uint64_t bcue_setup_err : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t internal_err : 1; + uint64_t illegal_cache_op : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t axpush_wrerr : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axflow_err : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_rsverr : 1; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t reserved41 : 3; + uint64_t fir_parity_err2 : 1; + uint64_t fir_parity_err : 1; + uint64_t _reserved0 : 18; +#else + uint64_t _reserved0 : 18; + uint64_t fir_parity_err : 1; + uint64_t fir_parity_err2 : 1; + uint64_t reserved41 : 3; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t axsnd_rsverr : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axflow_err : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axpush_wrerr : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t illegal_cache_op : 1; + uint64_t internal_err : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_setup_err : 1; + uint64_t pb_crespto : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_unexpcresp : 1; + uint64_t oci_rereqto : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_slave_init : 1; + uint64_t pb_ce_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t oci_apar_err : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_firmask_t; + + + +typedef union pba_firmask_and { + + 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 oci_apar_err : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_ce_fw : 1; + uint64_t oci_slave_init : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_rereqto : 1; + uint64_t pb_unexpcresp : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_crespto : 1; + uint64_t bcue_setup_err : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t internal_err : 1; + uint64_t illegal_cache_op : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t axpush_wrerr : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axflow_err : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_rsverr : 1; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t reserved41 : 3; + uint64_t fir_parity_err2 : 1; + uint64_t fir_parity_err : 1; + uint64_t _reserved0 : 18; +#else + uint64_t _reserved0 : 18; + uint64_t fir_parity_err : 1; + uint64_t fir_parity_err2 : 1; + uint64_t reserved41 : 3; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t axsnd_rsverr : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axflow_err : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axpush_wrerr : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t illegal_cache_op : 1; + uint64_t internal_err : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_setup_err : 1; + uint64_t pb_crespto : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_unexpcresp : 1; + uint64_t oci_rereqto : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_slave_init : 1; + uint64_t pb_ce_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t oci_apar_err : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_firmask_and_t; + + + +typedef union pba_firmask_or { + + 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 oci_apar_err : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_ce_fw : 1; + uint64_t oci_slave_init : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_rereqto : 1; + uint64_t pb_unexpcresp : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_crespto : 1; + uint64_t bcue_setup_err : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t internal_err : 1; + uint64_t illegal_cache_op : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t axpush_wrerr : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axflow_err : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_rsverr : 1; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t reserved41 : 3; + uint64_t fir_parity_err2 : 1; + uint64_t fir_parity_err : 1; + uint64_t _reserved0 : 18; +#else + uint64_t _reserved0 : 18; + uint64_t fir_parity_err : 1; + uint64_t fir_parity_err2 : 1; + uint64_t reserved41 : 3; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t axsnd_rsverr : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axflow_err : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axpush_wrerr : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t illegal_cache_op : 1; + uint64_t internal_err : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_setup_err : 1; + uint64_t pb_crespto : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_unexpcresp : 1; + uint64_t oci_rereqto : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_slave_init : 1; + uint64_t pb_ce_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t oci_apar_err : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_firmask_or_t; + + + +typedef union pba_firact0 { + + 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 oci_apar_err : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_ce_fw : 1; + uint64_t oci_slave_init : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_rereqto : 1; + uint64_t pb_unexpcresp : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_crespto : 1; + uint64_t bcue_setup_err : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t internal_err : 1; + uint64_t illegal_cache_op : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t axpush_wrerr : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axflow_err : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_rsverr : 1; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t reserved41 : 3; + uint64_t fir_parity_err2 : 1; + uint64_t fir_parity_err : 1; + uint64_t _reserved0 : 18; +#else + uint64_t _reserved0 : 18; + uint64_t fir_parity_err : 1; + uint64_t fir_parity_err2 : 1; + uint64_t reserved41 : 3; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t axsnd_rsverr : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axflow_err : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axpush_wrerr : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t illegal_cache_op : 1; + uint64_t internal_err : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_setup_err : 1; + uint64_t pb_crespto : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_unexpcresp : 1; + uint64_t oci_rereqto : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_slave_init : 1; + uint64_t pb_ce_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t oci_apar_err : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_firact0_t; + + + +typedef union pba_firact1 { + + 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 oci_apar_err : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_ce_fw : 1; + uint64_t oci_slave_init : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_rereqto : 1; + uint64_t pb_unexpcresp : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_crespto : 1; + uint64_t bcue_setup_err : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t internal_err : 1; + uint64_t illegal_cache_op : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t axpush_wrerr : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axflow_err : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_rsverr : 1; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t reserved41 : 3; + uint64_t fir_parity_err2 : 1; + uint64_t fir_parity_err : 1; + uint64_t _reserved0 : 18; +#else + uint64_t _reserved0 : 18; + uint64_t fir_parity_err : 1; + uint64_t fir_parity_err2 : 1; + uint64_t reserved41 : 3; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t axsnd_rsverr : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axflow_err : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axpush_wrerr : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t illegal_cache_op : 1; + uint64_t internal_err : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_setup_err : 1; + uint64_t pb_crespto : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_unexpcresp : 1; + uint64_t oci_rereqto : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_slave_init : 1; + uint64_t pb_ce_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t oci_apar_err : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_firact1_t; + + + +typedef union pba_occact { + + 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 oci_apar_err : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_ce_fw : 1; + uint64_t oci_slave_init : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_rereqto : 1; + uint64_t pb_unexpcresp : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_crespto : 1; + uint64_t bcue_setup_err : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t internal_err : 1; + uint64_t illegal_cache_op : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t axpush_wrerr : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axflow_err : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_rsverr : 1; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t reserved41 : 3; + uint64_t fir_parity_err2 : 1; + uint64_t fir_parity_err : 1; + uint64_t _reserved0 : 18; +#else + uint64_t _reserved0 : 18; + uint64_t fir_parity_err : 1; + uint64_t fir_parity_err2 : 1; + uint64_t reserved41 : 3; + uint64_t pb_ackdead_fw_wr : 1; + uint64_t axsnd_rsverr : 1; + uint64_t axsnd_rsvto : 1; + uint64_t axsnd_dlo_rtyto : 1; + uint64_t axsnd_dhi_rtyto : 1; + uint64_t axflow_err : 1; + uint64_t axrcv_rsvdata_to : 1; + uint64_t axrcv_dlo_to : 1; + uint64_t axrcv_dlo_err : 1; + uint64_t axpush_wrerr : 1; + uint64_t oci_bad_reg_addr : 1; + uint64_t illegal_cache_op : 1; + uint64_t internal_err : 1; + uint64_t bcde_oci_dataerr : 1; + uint64_t bcde_ce : 1; + uint64_t bcde_ue_err : 1; + uint64_t bcde_sue_err : 1; + uint64_t bcde_rddatato_err : 1; + uint64_t bcde_pb_adrerr : 1; + uint64_t bcde_pb_ack_dead : 1; + uint64_t bcde_setup_err : 1; + uint64_t bcue_oci_dataerr : 1; + uint64_t bcue_pb_adrerr : 1; + uint64_t bcue_pb_ack_dead : 1; + uint64_t bcue_setup_err : 1; + uint64_t pb_crespto : 1; + uint64_t pb_ackdead_fw : 1; + uint64_t pb_badcresp : 1; + uint64_t pb_wradrerr_fw : 1; + uint64_t pb_parity_err : 1; + uint64_t pb_unexpdata : 1; + uint64_t pb_unexpcresp : 1; + uint64_t oci_rereqto : 1; + uint64_t oci_wrpar_err : 1; + uint64_t oci_slave_init : 1; + uint64_t pb_ce_fw : 1; + uint64_t pb_ue_fw : 1; + uint64_t pb_sue_fw : 1; + uint64_t pb_rddatato_fw : 1; + uint64_t pb_rdadrerr_fw : 1; + uint64_t oci_apar_err : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_occact_t; + + + +typedef union pba_cfg { + + 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 pbreq_slvfw_max_priority : 2; + uint64_t pbreq_bce_max_priority : 2; + uint64_t pbreq_data_hang_div : 5; + uint64_t pbreq_oper_hang_div : 5; + uint64_t pbreq_drop_priority_mask : 6; + uint64_t reserved20 : 4; + uint64_t chsw_hang_on_adrerror : 1; + uint64_t chsw_dis_ociabuspar_check : 1; + uint64_t chsw_dis_ocibepar_check : 1; + uint64_t chsw_hang_on_derror : 1; + uint64_t chsw_hang_on_rereq_timeout : 1; + uint64_t chsw_dis_write_match_rearb : 1; + uint64_t chsw_dis_ocidatapar_gen : 1; + uint64_t chsw_dis_ocidatapar_check : 1; + uint64_t chsw_dis_oper_hang : 1; + uint64_t chsw_dis_data_hang : 1; + uint64_t chsw_dis_ecc_check : 1; + uint64_t chsw_dis_retry_backoff : 1; + uint64_t chsw_hang_on_invalid_cresp : 1; + uint64_t chsw_en_scopeinc_on_bkill_inc : 1; + uint64_t chsw_dis_group_scope : 1; + uint64_t chsw_dis_rtag_parity_chk : 1; + uint64_t chsw_dis_pb_parity_chk : 1; + uint64_t _reserved0 : 23; +#else + uint64_t _reserved0 : 23; + uint64_t chsw_dis_pb_parity_chk : 1; + uint64_t chsw_dis_rtag_parity_chk : 1; + uint64_t chsw_dis_group_scope : 1; + uint64_t chsw_en_scopeinc_on_bkill_inc : 1; + uint64_t chsw_hang_on_invalid_cresp : 1; + uint64_t chsw_dis_retry_backoff : 1; + uint64_t chsw_dis_ecc_check : 1; + uint64_t chsw_dis_data_hang : 1; + uint64_t chsw_dis_oper_hang : 1; + uint64_t chsw_dis_ocidatapar_check : 1; + uint64_t chsw_dis_ocidatapar_gen : 1; + uint64_t chsw_dis_write_match_rearb : 1; + uint64_t chsw_hang_on_rereq_timeout : 1; + uint64_t chsw_hang_on_derror : 1; + uint64_t chsw_dis_ocibepar_check : 1; + uint64_t chsw_dis_ociabuspar_check : 1; + uint64_t chsw_hang_on_adrerror : 1; + uint64_t reserved20 : 4; + uint64_t pbreq_drop_priority_mask : 6; + uint64_t pbreq_oper_hang_div : 5; + uint64_t pbreq_data_hang_div : 5; + uint64_t pbreq_bce_max_priority : 2; + uint64_t pbreq_slvfw_max_priority : 2; +#endif // _BIG_ENDIAN + } fields; +} pba_cfg_t; + + + +typedef union pba_errpt0 { + + 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 cerr_pb_rddatato_fw : 6; + uint64_t cerr_pb_rdadrerr_fw : 6; + uint64_t cerr_pb_wradrerr_fw : 4; + uint64_t cerr_pb_ackdead_fw_rd : 6; + uint64_t cerr_pb_ackdead_fw_wr : 2; + uint64_t cerr_pb_unexpcresp : 11; + uint64_t cerr_pb_unexpdata : 6; + uint64_t _reserved0 : 23; +#else + uint64_t _reserved0 : 23; + uint64_t cerr_pb_unexpdata : 6; + uint64_t cerr_pb_unexpcresp : 11; + uint64_t cerr_pb_ackdead_fw_wr : 2; + uint64_t cerr_pb_ackdead_fw_rd : 6; + uint64_t cerr_pb_wradrerr_fw : 4; + uint64_t cerr_pb_rdadrerr_fw : 6; + uint64_t cerr_pb_rddatato_fw : 6; +#endif // _BIG_ENDIAN + } fields; +} pba_errpt0_t; + + + +typedef union pba_errpt1 { + + 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 cerr_pb_badcresp : 12; + uint64_t cerr_pb_crespto : 12; + uint64_t cerr_oci_rereqto : 6; + uint64_t cerr_bcde_setup_err : 2; + uint64_t cerr_bcue_setup_err : 2; + uint64_t cerr_bcue_oci_dataerr : 2; + uint64_t _reserved0 : 28; +#else + uint64_t _reserved0 : 28; + uint64_t cerr_bcue_oci_dataerr : 2; + uint64_t cerr_bcue_setup_err : 2; + uint64_t cerr_bcde_setup_err : 2; + uint64_t cerr_oci_rereqto : 6; + uint64_t cerr_pb_crespto : 12; + uint64_t cerr_pb_badcresp : 12; +#endif // _BIG_ENDIAN + } fields; +} pba_errpt1_t; + + + +typedef union pba_errpt2 { + + 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 cerr_slv_internal_err : 8; + uint64_t cerr_bcde_internal_err : 4; + uint64_t cerr_bcue_internal_err : 4; + uint64_t cerr_bar_parity_err : 1; + uint64_t cerr_scomtb_err : 1; + uint64_t reserved18 : 2; + uint64_t cerr_pbdout_parity_err : 1; + uint64_t cerr_pb_parity_err : 3; + uint64_t cerr_axflow_err : 5; + uint64_t cerr_axpush_wrerr : 2; + uint64_t _reserved0 : 33; +#else + uint64_t _reserved0 : 33; + uint64_t cerr_axpush_wrerr : 2; + uint64_t cerr_axflow_err : 5; + uint64_t cerr_pb_parity_err : 3; + uint64_t cerr_pbdout_parity_err : 1; + uint64_t reserved18 : 2; + uint64_t cerr_scomtb_err : 1; + uint64_t cerr_bar_parity_err : 1; + uint64_t cerr_bcue_internal_err : 4; + uint64_t cerr_bcde_internal_err : 4; + uint64_t cerr_slv_internal_err : 8; +#endif // _BIG_ENDIAN + } fields; +} pba_errpt2_t; + + + +typedef union pba_rbufvaln { + + 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 rd_slvnum : 2; + uint64_t cur_rd_addr : 23; + uint64_t spare1 : 3; + uint64_t prefetch : 1; + uint64_t spare2 : 2; + uint64_t abort : 1; + uint64_t spare3 : 1; + uint64_t buffer_status : 7; + uint64_t spare4 : 1; + uint64_t masterid : 3; + uint64_t _reserved0 : 20; +#else + uint64_t _reserved0 : 20; + uint64_t masterid : 3; + uint64_t spare4 : 1; + uint64_t buffer_status : 7; + uint64_t spare3 : 1; + uint64_t abort : 1; + uint64_t spare2 : 2; + uint64_t prefetch : 1; + uint64_t spare1 : 3; + uint64_t cur_rd_addr : 23; + uint64_t rd_slvnum : 2; +#endif // _BIG_ENDIAN + } fields; +} pba_rbufvaln_t; + + + +typedef union pba_wbufvaln { + + 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 wr_slvnum : 2; + uint64_t start_wr_addr : 30; + uint64_t spare1 : 3; + uint64_t wr_buffer_status : 5; + uint64_t spare2 : 1; + uint64_t wr_byte_count : 7; + uint64_t spare3 : 16; +#else + uint64_t spare3 : 16; + uint64_t wr_byte_count : 7; + uint64_t spare2 : 1; + uint64_t wr_buffer_status : 5; + uint64_t spare1 : 3; + uint64_t start_wr_addr : 30; + uint64_t wr_slvnum : 2; +#endif // _BIG_ENDIAN + } fields; +} pba_wbufvaln_t; + + + +typedef union pba_mode { + + 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 reserved0 : 4; + uint64_t dis_rearb : 1; + uint64_t dis_mstid_match_pref_inv : 1; + uint64_t dis_slave_rdpipe : 1; + uint64_t dis_slave_wrpipe : 1; + uint64_t en_marker_ack : 1; + uint64_t dis_slvmatch_order : 1; + uint64_t en_second_wrbuf : 1; + uint64_t dis_rerequest_to : 1; + uint64_t inject_type : 2; + uint64_t inject_mode : 2; + uint64_t pba_region : 2; + uint64_t oci_marker_space : 3; + uint64_t bcde_ocitrans : 2; + uint64_t bcue_ocitrans : 2; + uint64_t dis_master_rd_pipe : 1; + uint64_t dis_master_wr_pipe : 1; + uint64_t en_slave_fairness : 1; + uint64_t en_event_count : 1; + uint64_t pb_noci_event_sel : 1; + uint64_t slv_event_mux : 2; + uint64_t enable_debug_bus : 1; + uint64_t debug_pb_not_oci : 1; + uint64_t debug_oci_mode : 5; + uint64_t reserved2 : 1; + uint64_t ocislv_fairness_mask : 5; + uint64_t ocislv_rereq_hang_div : 5; + uint64_t dis_chgrate_count : 1; + uint64_t pbreq_event_mux : 2; + uint64_t _reserved0 : 11; +#else + uint64_t _reserved0 : 11; + uint64_t pbreq_event_mux : 2; + uint64_t dis_chgrate_count : 1; + uint64_t ocislv_rereq_hang_div : 5; + uint64_t ocislv_fairness_mask : 5; + uint64_t reserved2 : 1; + uint64_t debug_oci_mode : 5; + uint64_t debug_pb_not_oci : 1; + uint64_t enable_debug_bus : 1; + uint64_t slv_event_mux : 2; + uint64_t pb_noci_event_sel : 1; + uint64_t en_event_count : 1; + uint64_t en_slave_fairness : 1; + uint64_t dis_master_wr_pipe : 1; + uint64_t dis_master_rd_pipe : 1; + uint64_t bcue_ocitrans : 2; + uint64_t bcde_ocitrans : 2; + uint64_t oci_marker_space : 3; + uint64_t pba_region : 2; + uint64_t inject_mode : 2; + uint64_t inject_type : 2; + uint64_t dis_rerequest_to : 1; + uint64_t en_second_wrbuf : 1; + uint64_t dis_slvmatch_order : 1; + uint64_t en_marker_ack : 1; + uint64_t dis_slave_wrpipe : 1; + uint64_t dis_slave_rdpipe : 1; + uint64_t dis_mstid_match_pref_inv : 1; + uint64_t dis_rearb : 1; + uint64_t reserved0 : 4; +#endif // _BIG_ENDIAN + } fields; +} pba_mode_t; + + + +typedef union pba_slvrst { + + 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 set : 3; + uint64_t notimp1 : 1; + uint64_t in_prog : 4; + uint64_t busy_status : 4; + uint64_t _reserved0 : 52; +#else + uint64_t _reserved0 : 52; + uint64_t busy_status : 4; + uint64_t in_prog : 4; + uint64_t notimp1 : 1; + uint64_t set : 3; +#endif // _BIG_ENDIAN + } fields; +} pba_slvrst_t; + + + +typedef union pba_slvctln { + + 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 enable : 1; + uint64_t mid_match_value : 3; + uint64_t _reserved0 : 1; + uint64_t mid_care_mask : 3; + uint64_t write_ttype : 3; + uint64_t _reserved1 : 4; + uint64_t read_ttype : 1; + uint64_t read_prefetch_ctl : 2; + uint64_t buf_invalidate_ctl : 1; + uint64_t buf_alloc_w : 1; + uint64_t buf_alloc_a : 1; + uint64_t buf_alloc_b : 1; + uint64_t buf_alloc_c : 1; + uint64_t _reserved2 : 1; + uint64_t dis_write_gather : 1; + uint64_t wr_gather_timeout : 3; + uint64_t write_tsize : 7; + uint64_t extaddr : 14; + uint64_t _reserved3 : 15; +#else + uint64_t _reserved3 : 15; + uint64_t extaddr : 14; + uint64_t write_tsize : 7; + uint64_t wr_gather_timeout : 3; + uint64_t dis_write_gather : 1; + uint64_t _reserved2 : 1; + uint64_t buf_alloc_c : 1; + uint64_t buf_alloc_b : 1; + uint64_t buf_alloc_a : 1; + uint64_t buf_alloc_w : 1; + uint64_t buf_invalidate_ctl : 1; + uint64_t read_prefetch_ctl : 2; + uint64_t read_ttype : 1; + uint64_t _reserved1 : 4; + uint64_t write_ttype : 3; + uint64_t mid_care_mask : 3; + uint64_t _reserved0 : 1; + uint64_t mid_match_value : 3; + uint64_t enable : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_slvctln_t; + + + +typedef union pba_bcde_ctl { + + 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 stop : 1; + uint64_t start : 1; + uint64_t _reserved0 : 62; +#else + uint64_t _reserved0 : 62; + uint64_t start : 1; + uint64_t stop : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_bcde_ctl_t; + +#endif // __ASSEMBLER__ +#define PBA_BCDE_CTL_STOP SIXTYFOUR_BIT_CONSTANT(0x8000000000000000) +#define PBA_BCDE_CTL_START SIXTYFOUR_BIT_CONSTANT(0x4000000000000000) +#ifndef __ASSEMBLER__ + + +typedef union pba_bcde_set { + + 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 _reserved0 : 2; + uint64_t copy_length : 6; + uint64_t _reserved1 : 56; +#else + uint64_t _reserved1 : 56; + uint64_t copy_length : 6; + uint64_t _reserved0 : 2; +#endif // _BIG_ENDIAN + } fields; +} pba_bcde_set_t; + + + +typedef union pba_bcde_stat { + + 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 running : 1; + uint64_t waiting : 1; + uint64_t wrcmp : 6; + uint64_t _reserved0 : 6; + uint64_t rdcmp : 6; + uint64_t debug : 9; + uint64_t stopped : 1; + uint64_t error : 1; + uint64_t done : 1; + uint64_t _reserved1 : 32; +#else + uint64_t _reserved1 : 32; + uint64_t done : 1; + uint64_t error : 1; + uint64_t stopped : 1; + uint64_t debug : 9; + uint64_t rdcmp : 6; + uint64_t _reserved0 : 6; + uint64_t wrcmp : 6; + uint64_t waiting : 1; + uint64_t running : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_bcde_stat_t; + + + +typedef union pba_bcde_pbadr { + + 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 _reserved0 : 2; + uint64_t pb_offset : 23; + uint64_t _reserved1 : 2; + uint64_t extaddr : 14; + uint64_t _reserved2 : 23; +#else + uint64_t _reserved2 : 23; + uint64_t extaddr : 14; + uint64_t _reserved1 : 2; + uint64_t pb_offset : 23; + uint64_t _reserved0 : 2; +#endif // _BIG_ENDIAN + } fields; +} pba_bcde_pbadr_t; + + + +typedef union pba_bcde_ocibar { + + 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 addr : 25; + uint64_t _reserved0 : 39; +#else + uint64_t _reserved0 : 39; + uint64_t addr : 25; +#endif // _BIG_ENDIAN + } fields; +} pba_bcde_ocibar_t; + + + +typedef union pba_bcue_ctl { + + 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 stop : 1; + uint64_t start : 1; + uint64_t _reserved0 : 62; +#else + uint64_t _reserved0 : 62; + uint64_t start : 1; + uint64_t stop : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_bcue_ctl_t; + +#endif // __ASSEMBLER__ +#define PBA_BCUE_CTL_STOP SIXTYFOUR_BIT_CONSTANT(0x8000000000000000) +#define PBA_BCUE_CTL_START SIXTYFOUR_BIT_CONSTANT(0x4000000000000000) +#ifndef __ASSEMBLER__ + + +typedef union pba_bcue_set { + + 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 _reserved0 : 2; + uint64_t copy_length : 6; + uint64_t _reserved1 : 56; +#else + uint64_t _reserved1 : 56; + uint64_t copy_length : 6; + uint64_t _reserved0 : 2; +#endif // _BIG_ENDIAN + } fields; +} pba_bcue_set_t; + + + +typedef union pba_bcue_stat { + + 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 running : 1; + uint64_t waiting : 1; + uint64_t wrcmp : 6; + uint64_t _reserved0 : 6; + uint64_t rdcmp : 6; + uint64_t debug : 9; + uint64_t stopped : 1; + uint64_t error : 1; + uint64_t done : 1; + uint64_t _reserved1 : 32; +#else + uint64_t _reserved1 : 32; + uint64_t done : 1; + uint64_t error : 1; + uint64_t stopped : 1; + uint64_t debug : 9; + uint64_t rdcmp : 6; + uint64_t _reserved0 : 6; + uint64_t wrcmp : 6; + uint64_t waiting : 1; + uint64_t running : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_bcue_stat_t; + + + +typedef union pba_bcue_pbadr { + + 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 _reserved0 : 2; + uint64_t pb_offset : 23; + uint64_t _reserved1 : 2; + uint64_t extaddr : 14; + uint64_t _reserved2 : 23; +#else + uint64_t _reserved2 : 23; + uint64_t extaddr : 14; + uint64_t _reserved1 : 2; + uint64_t pb_offset : 23; + uint64_t _reserved0 : 2; +#endif // _BIG_ENDIAN + } fields; +} pba_bcue_pbadr_t; + + + +typedef union pba_bcue_ocibar { + + 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 addr : 25; + uint64_t _reserved0 : 39; +#else + uint64_t _reserved0 : 39; + uint64_t addr : 25; +#endif // _BIG_ENDIAN + } fields; +} pba_bcue_ocibar_t; + + + +typedef union pba_pbocrn { + + 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 _reserved0 : 16; + uint64_t event : 16; + uint64_t _reserved1 : 12; + uint64_t accum : 20; +#else + uint64_t accum : 20; + uint64_t _reserved1 : 12; + uint64_t event : 16; + uint64_t _reserved0 : 16; +#endif // _BIG_ENDIAN + } fields; +} pba_pbocrn_t; + + + +typedef union pba_xsndtx { + + 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 snd_scope : 3; + uint64_t snd_qid : 1; + uint64_t snd_type : 1; + uint64_t snd_reservation : 1; + uint64_t spare6 : 2; + uint64_t snd_nodeid : 3; + uint64_t snd_chipid : 3; + uint64_t spare14 : 2; + uint64_t _reserved0 : 48; +#else + uint64_t _reserved0 : 48; + uint64_t spare14 : 2; + uint64_t snd_chipid : 3; + uint64_t snd_nodeid : 3; + uint64_t spare6 : 2; + uint64_t snd_reservation : 1; + uint64_t snd_type : 1; + uint64_t snd_qid : 1; + uint64_t snd_scope : 3; +#endif // _BIG_ENDIAN + } fields; +} pba_xsndtx_t; + + + +typedef union pba_xcfg { + + 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 pbax_en : 1; + uint64_t reservation_en : 1; + uint64_t snd_reset : 1; + uint64_t rcv_reset : 1; + uint64_t rcv_nodeid : 3; + uint64_t rcv_chipid : 3; + uint64_t spare10 : 2; + uint64_t rcv_brdcst_group : 8; + uint64_t rcv_datato_div : 5; + uint64_t spare25 : 2; + uint64_t snd_retry_count_overcom : 1; + uint64_t snd_retry_thresh : 8; + uint64_t snd_rsvto_div : 5; + uint64_t _reserved0 : 23; +#else + uint64_t _reserved0 : 23; + uint64_t snd_rsvto_div : 5; + uint64_t snd_retry_thresh : 8; + uint64_t snd_retry_count_overcom : 1; + uint64_t spare25 : 2; + uint64_t rcv_datato_div : 5; + uint64_t rcv_brdcst_group : 8; + uint64_t spare10 : 2; + uint64_t rcv_chipid : 3; + uint64_t rcv_nodeid : 3; + uint64_t rcv_reset : 1; + uint64_t snd_reset : 1; + uint64_t reservation_en : 1; + uint64_t pbax_en : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_xcfg_t; + + + +typedef union pba_xsndstat { + + 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 snd_in_progress : 1; + uint64_t snd_error : 1; + uint64_t snd_status : 6; + uint64_t snd_retry_count : 8; + uint64_t _reserved0 : 48; +#else + uint64_t _reserved0 : 48; + uint64_t snd_retry_count : 8; + uint64_t snd_status : 6; + uint64_t snd_error : 1; + uint64_t snd_in_progress : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_xsndstat_t; + + + +typedef union pba_xsnddat { + + 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 pbax_datahi : 32; + uint64_t pbax_datalo : 32; +#else + uint64_t pbax_datalo : 32; + uint64_t pbax_datahi : 32; +#endif // _BIG_ENDIAN + } fields; +} pba_xsnddat_t; + + + +typedef union pba_xrcvstat { + + 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 rcv_in_progress : 1; + uint64_t rcv_error : 1; + uint64_t rcv_write_in_progress : 1; + uint64_t rcv_reservation_set : 1; + uint64_t rcv_capture : 14; + uint64_t _reserved0 : 46; +#else + uint64_t _reserved0 : 46; + uint64_t rcv_capture : 14; + uint64_t rcv_reservation_set : 1; + uint64_t rcv_write_in_progress : 1; + uint64_t rcv_error : 1; + uint64_t rcv_in_progress : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_xrcvstat_t; + + + +typedef union pba_xshbrn { + + 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 push_start : 29; + uint64_t _reserved0 : 35; +#else + uint64_t _reserved0 : 35; + uint64_t push_start : 29; +#endif // _BIG_ENDIAN + } fields; +} pba_xshbrn_t; + + + +typedef union pba_xshcsn { + + 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 push_full : 1; + uint64_t push_empty : 1; + uint64_t spare1 : 2; + uint64_t push_intr_action : 2; + uint64_t push_length : 5; + uint64_t notimp1 : 2; + uint64_t push_write_ptr : 5; + uint64_t notimp2 : 3; + uint64_t push_read_ptr : 5; + uint64_t notimp3 : 5; + uint64_t push_enable : 1; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t push_enable : 1; + uint64_t notimp3 : 5; + uint64_t push_read_ptr : 5; + uint64_t notimp2 : 3; + uint64_t push_write_ptr : 5; + uint64_t notimp1 : 2; + uint64_t push_length : 5; + uint64_t push_intr_action : 2; + uint64_t spare1 : 2; + uint64_t push_empty : 1; + uint64_t push_full : 1; +#endif // _BIG_ENDIAN + } fields; +} pba_xshcsn_t; + + + +typedef union pba_xshincn { + + 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 reserved : 64; +#else + uint64_t reserved : 64; +#endif // _BIG_ENDIAN + } fields; +} pba_xshincn_t; + + +#endif // __ASSEMBLER__ +#endif // __PBA_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/pba_register_addresses.h b/src/ssx/pgp/registers/pba_register_addresses.h new file mode 100755 index 0000000..1703629 --- /dev/null +++ b/src/ssx/pgp/registers/pba_register_addresses.h @@ -0,0 +1,94 @@ +#ifndef __PBA_REGISTER_ADDRESSES_H__ +#define __PBA_REGISTER_ADDRESSES_H__ + +// $Id: pba_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pba_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pba_register_addresses.h +/// \brief Symbolic addresses for the PBA unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define TRUSTEDPIB_BASE 0x02013f00 +#define PBA_BARN(n) (PBA_BAR0 + ((PBA_BAR1 - PBA_BAR0) * (n))) +#define PBA_BAR0 0x02013f00 +#define PBA_BAR1 0x02013f01 +#define PBA_BAR2 0x02013f02 +#define PBA_BAR3 0x02013f03 +#define PBA_BARMSKN(n) (PBA_BARMSK0 + ((PBA_BARMSK1 - PBA_BARMSK0) * (n))) +#define PBA_BARMSK0 0x02013f04 +#define PBA_BARMSK1 0x02013f05 +#define PBA_BARMSK2 0x02013f06 +#define PBA_BARMSK3 0x02013f07 +#define PIB_BASE 0x02010840 +#define PBA_FIR 0x02010840 +#define PBA_FIR_AND 0x02010841 +#define PBA_FIR_OR 0x02010842 +#define PBA_FIRMASK 0x02010843 +#define PBA_FIRMASK_AND 0x02010844 +#define PBA_FIRMASK_OR 0x02010845 +#define PBA_FIRACT0 0x02010846 +#define PBA_FIRACT1 0x02010847 +#define PBA_OCCACT 0x0201084a +#define PBA_CFG 0x0201084b +#define PBA_ERRPT0 0x0201084c +#define PBA_ERRPT1 0x0201084d +#define PBA_ERRPT2 0x0201084e +#define PBA_RBUFVALN(n) (PBA_RBUFVAL0 + ((PBA_RBUFVAL1 - PBA_RBUFVAL0) * (n))) +#define PBA_RBUFVAL0 0x02010850 +#define PBA_RBUFVAL1 0x02010851 +#define PBA_RBUFVAL2 0x02010852 +#define PBA_RBUFVAL3 0x02010853 +#define PBA_RBUFVAL4 0x02010854 +#define PBA_RBUFVAL5 0x02010855 +#define PBA_WBUFVALN(n) (PBA_WBUFVAL0 + ((PBA_WBUFVAL1 - PBA_WBUFVAL0) * (n))) +#define PBA_WBUFVAL0 0x02010858 +#define PBA_WBUFVAL1 0x02010859 +#define OCI_BASE 0x40020000 +#define PBA_MODE 0x40020000 +#define PBA_SLVRST 0x40020008 +#define PBA_SLVCTLN(n) (PBA_SLVCTL0 + ((PBA_SLVCTL1 - PBA_SLVCTL0) * (n))) +#define PBA_SLVCTL0 0x40020020 +#define PBA_SLVCTL1 0x40020028 +#define PBA_SLVCTL2 0x40020030 +#define PBA_SLVCTL3 0x40020038 +#define PBA_BCDE_CTL 0x40020080 +#define PBA_BCDE_SET 0x40020088 +#define PBA_BCDE_STAT 0x40020090 +#define PBA_BCDE_PBADR 0x40020098 +#define PBA_BCDE_OCIBAR 0x400200a0 +#define PBA_BCUE_CTL 0x400200a8 +#define PBA_BCUE_SET 0x400200b0 +#define PBA_BCUE_STAT 0x400200b8 +#define PBA_BCUE_PBADR 0x400200c0 +#define PBA_BCUE_OCIBAR 0x400200c8 +#define PBA_PBOCRN(n) (PBA_PBOCR0 + ((PBA_PBOCR1 - PBA_PBOCR0) * (n))) +#define PBA_PBOCR0 0x400200d0 +#define PBA_PBOCR1 0x400200d8 +#define PBA_PBOCR2 0x400200e0 +#define PBA_PBOCR3 0x400200e8 +#define PBA_PBOCR4 0x400200f0 +#define PBA_PBOCR5 0x400200f8 +#define PBA_XSNDTX 0x40020100 +#define PBA_XCFG 0x40020108 +#define PBA_XSNDSTAT 0x40020110 +#define PBA_XSNDDAT 0x40020118 +#define PBA_XRCVSTAT 0x40020120 +#define PBA_XSHBRN(n) (PBA_XSHBR0 + ((PBA_XSHBR1 - PBA_XSHBR0) * (n))) +#define PBA_XSHBR0 0x40020130 +#define PBA_XSHBR1 0x40020150 +#define PBA_XSHCSN(n) (PBA_XSHCS0 + ((PBA_XSHCS1 - PBA_XSHCS0) * (n))) +#define PBA_XSHCS0 0x40020138 +#define PBA_XSHCS1 0x40020158 +#define PBA_XSHINCN(n) (PBA_XSHINC0 + ((PBA_XSHINC1 - PBA_XSHINC0) * (n))) +#define PBA_XSHINC0 0x40020140 +#define PBA_XSHINC1 0x40020160 + +#endif // __PBA_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/pc_firmware_registers.h b/src/ssx/pgp/registers/pc_firmware_registers.h new file mode 100755 index 0000000..2c86308 --- /dev/null +++ b/src/ssx/pgp/registers/pc_firmware_registers.h @@ -0,0 +1,442 @@ +#ifndef __PC_FIRMWARE_REGISTERS_H__ +#define __PC_FIRMWARE_REGISTERS_H__ + +// $Id: pc_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pc_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pc_firmware_registers.h +/// \brief C register structs for the PC unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union pc_pfth_modereg { + + 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 pfth_cntr_dis : 1; + uint64_t pfth_charac_mode : 1; + uint64_t pfth_cntr_run_latch_gate_dis : 1; + uint64_t sprd_pfth_tx_run_latches : 8; + uint64_t tx_threads_stopped : 8; + uint64_t _reserved0 : 45; +#else + uint64_t _reserved0 : 45; + uint64_t tx_threads_stopped : 8; + uint64_t sprd_pfth_tx_run_latches : 8; + uint64_t pfth_cntr_run_latch_gate_dis : 1; + uint64_t pfth_charac_mode : 1; + uint64_t pfth_cntr_dis : 1; +#endif // _BIG_ENDIAN + } fields; +} pc_pfth_modereg_t; + + + +typedef union pc_occ_sprc { + + 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 reserved0 : 53; + uint64_t autoinc : 1; + uint64_t sprn : 7; + uint64_t reserved1 : 3; +#else + uint64_t reserved1 : 3; + uint64_t sprn : 7; + uint64_t autoinc : 1; + uint64_t reserved0 : 53; +#endif // _BIG_ENDIAN + } fields; +} pc_occ_sprc_t; + + + +typedef union pc_occ_sprd { + + 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; +} pc_occ_sprd_t; + + + +typedef union pc_pfth_oha_instr_cnt_sel { + + 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 _reserved0 : 62; + uint64_t value : 2; +#else + uint64_t value : 2; + uint64_t _reserved0 : 62; +#endif // _BIG_ENDIAN + } fields; +} pc_pfth_oha_instr_cnt_sel_t; + + + +typedef union pc_pfth_throt_reg { + + 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 didt_trigger_enable : 1; + uint64_t isu_trigger_enable : 1; + uint64_t didt_throttle : 2; + uint64_t uthrottle : 2; + uint64_t force_suppress_speedup : 1; + uint64_t suppress_speedup_on_throttle : 1; + uint64_t core_slowdown : 1; + uint64_t suppress_on_slowdown : 1; + uint64_t isu_only_count_mode : 1; + uint64_t spare : 5; + uint64_t reserved : 48; +#else + uint64_t reserved : 48; + uint64_t spare : 5; + uint64_t isu_only_count_mode : 1; + uint64_t suppress_on_slowdown : 1; + uint64_t core_slowdown : 1; + uint64_t suppress_speedup_on_throttle : 1; + uint64_t force_suppress_speedup : 1; + uint64_t uthrottle : 2; + uint64_t didt_throttle : 2; + uint64_t isu_trigger_enable : 1; + uint64_t didt_trigger_enable : 1; +#endif // _BIG_ENDIAN + } fields; +} pc_pfth_throt_reg_t; + + + +typedef union pc_direct_controln { + + 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 reserved0 : 42; + uint64_t dc_prestart_sleep : 1; + uint64_t dc_prestart_winkle : 1; + uint64_t dc_clear_maint : 1; + uint64_t dc_ntc_flush : 1; + uint64_t reserved46 : 1; + uint64_t dc_prestart_nap : 1; + uint64_t dc_cancel_lost : 1; + uint64_t dc_reset_maint : 1; + uint64_t reserved50 : 1; + uint64_t dc_set_maint : 1; + uint64_t dc_goto_quiesce_state : 1; + uint64_t reserved53 : 1; + uint64_t dc_inj_test_hang : 2; + uint64_t dc_core_running : 1; + uint64_t dc_hang_inject : 1; + uint64_t dc_smt_start_suppress : 1; + uint64_t reserved59 : 1; + uint64_t dc_sreset_request : 1; + uint64_t dc_core_step : 1; + uint64_t dc_core_start : 1; + uint64_t dc_core_stop : 1; +#else + uint64_t dc_core_stop : 1; + uint64_t dc_core_start : 1; + uint64_t dc_core_step : 1; + uint64_t dc_sreset_request : 1; + uint64_t reserved59 : 1; + uint64_t dc_smt_start_suppress : 1; + uint64_t dc_hang_inject : 1; + uint64_t dc_core_running : 1; + uint64_t dc_inj_test_hang : 2; + uint64_t reserved53 : 1; + uint64_t dc_goto_quiesce_state : 1; + uint64_t dc_set_maint : 1; + uint64_t reserved50 : 1; + uint64_t dc_reset_maint : 1; + uint64_t dc_cancel_lost : 1; + uint64_t dc_prestart_nap : 1; + uint64_t reserved46 : 1; + uint64_t dc_ntc_flush : 1; + uint64_t dc_clear_maint : 1; + uint64_t dc_prestart_winkle : 1; + uint64_t dc_prestart_sleep : 1; + uint64_t reserved0 : 42; +#endif // _BIG_ENDIAN + } fields; +} pc_direct_controln_t; + + + +typedef union pc_ras_moderegn { + + 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 reserved0 : 43; + uint64_t mr_thread_in_debug_mode : 1; + uint64_t mr_pmon_inhibit : 1; + uint64_t mr_fence_interrupts : 1; + uint64_t mr_stop_fetch : 1; + uint64_t mr_stop_prefetch : 1; + uint64_t mr_stop_dispatch : 1; + uint64_t mr_single_decode : 1; + uint64_t mr_do_single_mode : 1; + uint64_t mr_one_ppc_mode : 1; + uint64_t mr_hang_test_ctrl : 2; + uint64_t mr_attempt_gps_hr : 3; + uint64_t mr_hang_dis : 1; + uint64_t mr_on_corehng : 1; + uint64_t mr_on_ambihng : 1; + uint64_t mr_on_nesthng : 1; + uint64_t mr_recov_enable : 1; + uint64_t mr_block_hmi_on_maint : 1; + uint64_t mr_fence_intr_on_checkstop : 1; +#else + uint64_t mr_fence_intr_on_checkstop : 1; + uint64_t mr_block_hmi_on_maint : 1; + uint64_t mr_recov_enable : 1; + uint64_t mr_on_nesthng : 1; + uint64_t mr_on_ambihng : 1; + uint64_t mr_on_corehng : 1; + uint64_t mr_hang_dis : 1; + uint64_t mr_attempt_gps_hr : 3; + uint64_t mr_hang_test_ctrl : 2; + uint64_t mr_one_ppc_mode : 1; + uint64_t mr_do_single_mode : 1; + uint64_t mr_single_decode : 1; + uint64_t mr_stop_dispatch : 1; + uint64_t mr_stop_prefetch : 1; + uint64_t mr_stop_fetch : 1; + uint64_t mr_fence_interrupts : 1; + uint64_t mr_pmon_inhibit : 1; + uint64_t mr_thread_in_debug_mode : 1; + uint64_t reserved0 : 43; +#endif // _BIG_ENDIAN + } fields; +} pc_ras_moderegn_t; + + + +typedef union pc_ras_statusn { + + 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 quiesce_status : 20; + uint64_t reserved20 : 1; + uint64_t reserved21 : 1; + uint64_t reserved22 : 1; + uint64_t other_thread_active : 1; + uint64_t hang_fsm : 3; + uint64_t reserved27 : 1; + uint64_t hang_hist0 : 1; + uint64_t hang_hist1 : 1; + uint64_t hang_hist2 : 1; + uint64_t hang_hist3 : 1; + uint64_t reserved32 : 1; + uint64_t hr_comp_cnt : 8; + uint64_t smt_dead_stop : 1; + uint64_t stop_fetch : 1; + uint64_t stop_dispatch : 1; + uint64_t stop_completion : 1; + uint64_t hold_decode : 1; + uint64_t reserved46 : 1; + uint64_t reserved47 : 1; + uint64_t thread_enabled : 1; + uint64_t pow_status_thread_state : 4; + uint64_t reserved53 : 1; + uint64_t maint_single_mode : 1; + uint64_t reserved55 : 1; + uint64_t reserved56 : 1; + uint64_t reserved57 : 7; +#else + uint64_t reserved57 : 7; + uint64_t reserved56 : 1; + uint64_t reserved55 : 1; + uint64_t maint_single_mode : 1; + uint64_t reserved53 : 1; + uint64_t pow_status_thread_state : 4; + uint64_t thread_enabled : 1; + uint64_t reserved47 : 1; + uint64_t reserved46 : 1; + uint64_t hold_decode : 1; + uint64_t stop_completion : 1; + uint64_t stop_dispatch : 1; + uint64_t stop_fetch : 1; + uint64_t smt_dead_stop : 1; + uint64_t hr_comp_cnt : 8; + uint64_t reserved32 : 1; + uint64_t hang_hist3 : 1; + uint64_t hang_hist2 : 1; + uint64_t hang_hist1 : 1; + uint64_t hang_hist0 : 1; + uint64_t reserved27 : 1; + uint64_t hang_fsm : 3; + uint64_t other_thread_active : 1; + uint64_t reserved22 : 1; + uint64_t reserved21 : 1; + uint64_t reserved20 : 1; + uint64_t quiesce_status : 20; +#endif // _BIG_ENDIAN + } fields; +} pc_ras_statusn_t; + + + +typedef union pc_pow_statusn { + + 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 thread_state : 4; + uint64_t thread_pow_state : 2; + uint64_t smt_mode : 3; + uint64_t hmi_intr : 1; + uint64_t maybe_ext_intr : 1; + uint64_t decr_intr : 1; + uint64_t maybe_debug_intr : 1; + uint64_t hdec_intr : 1; + uint64_t maybe_pmu_intr : 1; + uint64_t sp_attn_intr : 1; + uint64_t sreset_type : 3; + uint64_t reserved19 : 1; + uint64_t sreset_pending : 1; + uint64_t debug_fetch_stop : 1; + uint64_t async_pending : 1; + uint64_t core_pow_state : 3; + uint64_t reserved26 : 3; + uint64_t _reserved0 : 35; +#else + uint64_t _reserved0 : 35; + uint64_t reserved26 : 3; + uint64_t core_pow_state : 3; + uint64_t async_pending : 1; + uint64_t debug_fetch_stop : 1; + uint64_t sreset_pending : 1; + uint64_t reserved19 : 1; + uint64_t sreset_type : 3; + uint64_t sp_attn_intr : 1; + uint64_t maybe_pmu_intr : 1; + uint64_t hdec_intr : 1; + uint64_t maybe_debug_intr : 1; + uint64_t decr_intr : 1; + uint64_t maybe_ext_intr : 1; + uint64_t hmi_intr : 1; + uint64_t smt_mode : 3; + uint64_t thread_pow_state : 2; + uint64_t thread_state : 4; +#endif // _BIG_ENDIAN + } fields; +} pc_pow_statusn_t; + + +#endif // __ASSEMBLER__ +#endif // __PC_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/pc_register_addresses.h b/src/ssx/pgp/registers/pc_register_addresses.h new file mode 100755 index 0000000..8b9baf2 --- /dev/null +++ b/src/ssx/pgp/registers/pc_register_addresses.h @@ -0,0 +1,61 @@ +#ifndef __PC_REGISTER_ADDRESSES_H__ +#define __PC_REGISTER_ADDRESSES_H__ + +// $Id: pc_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pc_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pc_register_addresses.h +/// \brief Symbolic addresses for the PC unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define PC_PCB_BASE 0x10010000 +#define PC_PFTH_MODEREG 0x100132a7 +#define PC_OCC_SPRC 0x100132ab +#define PC_OCC_SPRD 0x100132ac +#define PC_PFTH_THROT_REG 0x100132ad +#define PC_DIRECT_CONTROLN(n) (PC_DIRECT_CONTROL0 + ((PC_DIRECT_CONTROL1 - PC_DIRECT_CONTROL0) * (n))) +#define PC_DIRECT_CONTROL0 0x10013000 +#define PC_DIRECT_CONTROL1 0x10013010 +#define PC_DIRECT_CONTROL2 0x10013020 +#define PC_DIRECT_CONTROL3 0x10013030 +#define PC_DIRECT_CONTROL4 0x10013040 +#define PC_DIRECT_CONTROL5 0x10013050 +#define PC_DIRECT_CONTROL6 0x10013060 +#define PC_DIRECT_CONTROL7 0x10013070 +#define PC_RAS_MODEREGN(n) (PC_RAS_MODEREG0 + ((PC_RAS_MODEREG1 - PC_RAS_MODEREG0) * (n))) +#define PC_RAS_MODEREG0 0x10013001 +#define PC_RAS_MODEREG1 0x10013011 +#define PC_RAS_MODEREG2 0x10013021 +#define PC_RAS_MODEREG3 0x10013031 +#define PC_RAS_MODEREG4 0x10013041 +#define PC_RAS_MODEREG5 0x10013051 +#define PC_RAS_MODEREG6 0x10013061 +#define PC_RAS_MODEREG7 0x10013071 +#define PC_RAS_STATUSN(n) (PC_RAS_STATUS0 + ((PC_RAS_STATUS1 - PC_RAS_STATUS0) * (n))) +#define PC_RAS_STATUS0 0x10013002 +#define PC_RAS_STATUS1 0x10013012 +#define PC_RAS_STATUS2 0x10013022 +#define PC_RAS_STATUS3 0x10013032 +#define PC_RAS_STATUS4 0x10013042 +#define PC_RAS_STATUS5 0x10013052 +#define PC_RAS_STATUS6 0x10013062 +#define PC_RAS_STATUS7 0x10013072 +#define PC_POW_STATUSN(n) (PC_POW_STATUS0 + ((PC_POW_STATUS1 - PC_POW_STATUS0) * (n))) +#define PC_POW_STATUS0 0x10013004 +#define PC_POW_STATUS1 0x10013014 +#define PC_POW_STATUS2 0x10013024 +#define PC_POW_STATUS3 0x10013034 +#define PC_POW_STATUS4 0x10013044 +#define PC_POW_STATUS5 0x10013054 +#define PC_POW_STATUS6 0x10013064 +#define PC_POW_STATUS7 0x10013074 + +#endif // __PC_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/pcbs_firmware_registers.h b/src/ssx/pgp/registers/pcbs_firmware_registers.h new file mode 100755 index 0000000..1d268a2 --- /dev/null +++ b/src/ssx/pgp/registers/pcbs_firmware_registers.h @@ -0,0 +1,2477 @@ +#ifndef __PCBS_FIRMWARE_REGISTERS_H__ +#define __PCBS_FIRMWARE_REGISTERS_H__ + +// $Id: pcbs_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pcbs_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pcbs_firmware_registers.h +/// \brief C register structs for the PCBS unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union pcbs_pmgp0_reg { + + 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 pm_disable : 1; + uint64_t pmgp0_spare_bit1 : 1; + uint64_t tp_tc_restart_core_domain : 1; + uint64_t dpll_thold : 1; + uint64_t perv_thold : 1; + uint64_t cpm_cal_set_override_en : 1; + uint64_t cpm_cal_set_val : 1; + uint64_t pm_dpll_timer_ena : 1; + uint64_t dpll_lock_sense : 1; + uint64_t pmgp0_spare2 : 1; + uint64_t dpll_reset : 1; + uint64_t pmgp0_spare_bit11 : 1; + uint64_t dpll_testout_ctl : 8; + uint64_t tp_tc_cache2core_fence : 1; + uint64_t tp_tc_core2cache_fence : 1; + uint64_t tp_tc_pervasive_eco_fence : 1; + uint64_t chksw_hw257424_disable : 1; + uint64_t tp_clk_async_reset_dc : 3; + uint64_t tp_clkglm_sel_dc : 3; + uint64_t tp_clkglm_eco_sel_dc : 1; + uint64_t special_wkup_done : 1; + uint64_t tp_clkglm_core_sel_dc : 2; + uint64_t tp_clkglm_const_dc : 1; + uint64_t thold_timer_sel : 2; + uint64_t block_all_wakeup_sources : 1; + uint64_t tp_tc_dpll_testmode_dc : 1; + uint64_t pm_slv_winkle_fence : 1; + uint64_t l3_enable_switch : 1; + uint64_t tp_cplt_ivrm_refbypass_dc : 1; + uint64_t chksw_hw241939_disable : 1; + uint64_t chksw_hw273115_disable : 1; + uint64_t chksw_hw245103_disable : 1; + uint64_t chksw_hw257534_disable : 1; + uint64_t chksw_hw259509_enable : 1; + uint64_t pmgp0_spare3 : 1; + uint64_t wakeup_int_type : 2; + uint64_t dpll_lock : 1; + uint64_t special_wkup_all_sources_ored : 1; + uint64_t regular_wkup_available : 1; + uint64_t block_reg_wkup_sources : 1; + uint64_t _reserved0 : 10; +#else + uint64_t _reserved0 : 10; + uint64_t block_reg_wkup_sources : 1; + uint64_t regular_wkup_available : 1; + uint64_t special_wkup_all_sources_ored : 1; + uint64_t dpll_lock : 1; + uint64_t wakeup_int_type : 2; + uint64_t pmgp0_spare3 : 1; + uint64_t chksw_hw259509_enable : 1; + uint64_t chksw_hw257534_disable : 1; + uint64_t chksw_hw245103_disable : 1; + uint64_t chksw_hw273115_disable : 1; + uint64_t chksw_hw241939_disable : 1; + uint64_t tp_cplt_ivrm_refbypass_dc : 1; + uint64_t l3_enable_switch : 1; + uint64_t pm_slv_winkle_fence : 1; + uint64_t tp_tc_dpll_testmode_dc : 1; + uint64_t block_all_wakeup_sources : 1; + uint64_t thold_timer_sel : 2; + uint64_t tp_clkglm_const_dc : 1; + uint64_t tp_clkglm_core_sel_dc : 2; + uint64_t special_wkup_done : 1; + uint64_t tp_clkglm_eco_sel_dc : 1; + uint64_t tp_clkglm_sel_dc : 3; + uint64_t tp_clk_async_reset_dc : 3; + uint64_t chksw_hw257424_disable : 1; + uint64_t tp_tc_pervasive_eco_fence : 1; + uint64_t tp_tc_core2cache_fence : 1; + uint64_t tp_tc_cache2core_fence : 1; + uint64_t dpll_testout_ctl : 8; + uint64_t pmgp0_spare_bit11 : 1; + uint64_t dpll_reset : 1; + uint64_t pmgp0_spare2 : 1; + uint64_t dpll_lock_sense : 1; + uint64_t pm_dpll_timer_ena : 1; + uint64_t cpm_cal_set_val : 1; + uint64_t cpm_cal_set_override_en : 1; + uint64_t perv_thold : 1; + uint64_t dpll_thold : 1; + uint64_t tp_tc_restart_core_domain : 1; + uint64_t pmgp0_spare_bit1 : 1; + uint64_t pm_disable : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmgp0_reg_t; + + + +typedef union pcbs_pmgp0_reg_and { + + 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 pm_disable : 1; + uint64_t pmgp0_spare_bit1 : 1; + uint64_t tp_tc_restart_core_domain : 1; + uint64_t dpll_thold : 1; + uint64_t perv_thold : 1; + uint64_t cpm_cal_set_override_en : 1; + uint64_t cpm_cal_set_val : 1; + uint64_t pm_dpll_timer_ena : 1; + uint64_t dpll_lock_sense : 1; + uint64_t pmgp0_spare2 : 1; + uint64_t dpll_reset : 1; + uint64_t pmgp0_spare_bit11 : 1; + uint64_t dpll_testout_ctl : 8; + uint64_t tp_tc_cache2core_fence : 1; + uint64_t tp_tc_core2cache_fence : 1; + uint64_t tp_tc_pervasive_eco_fence : 1; + uint64_t chksw_hw257424_disable : 1; + uint64_t tp_clk_async_reset_dc : 3; + uint64_t tp_clkglm_sel_dc : 3; + uint64_t tp_clkglm_eco_sel_dc : 1; + uint64_t special_wkup_done : 1; + uint64_t tp_clkglm_core_sel_dc : 2; + uint64_t tp_clkglm_const_dc : 1; + uint64_t thold_timer_sel : 2; + uint64_t block_all_wakeup_sources : 1; + uint64_t tp_tc_dpll_testmode_dc : 1; + uint64_t pm_slv_winkle_fence : 1; + uint64_t l3_enable_switch : 1; + uint64_t tp_cplt_ivrm_refbypass_dc : 1; + uint64_t chksw_hw241939_disable : 1; + uint64_t chksw_hw273115_disable : 1; + uint64_t chksw_hw245103_disable : 1; + uint64_t chksw_hw257534_disable : 1; + uint64_t chksw_hw259509_enable : 1; + uint64_t pmgp0_spare3 : 1; + uint64_t wakeup_int_type : 2; + uint64_t dpll_lock : 1; + uint64_t special_wkup_all_sources_ored : 1; + uint64_t regular_wkup_available : 1; + uint64_t block_reg_wkup_sources : 1; + uint64_t _reserved0 : 10; +#else + uint64_t _reserved0 : 10; + uint64_t block_reg_wkup_sources : 1; + uint64_t regular_wkup_available : 1; + uint64_t special_wkup_all_sources_ored : 1; + uint64_t dpll_lock : 1; + uint64_t wakeup_int_type : 2; + uint64_t pmgp0_spare3 : 1; + uint64_t chksw_hw259509_enable : 1; + uint64_t chksw_hw257534_disable : 1; + uint64_t chksw_hw245103_disable : 1; + uint64_t chksw_hw273115_disable : 1; + uint64_t chksw_hw241939_disable : 1; + uint64_t tp_cplt_ivrm_refbypass_dc : 1; + uint64_t l3_enable_switch : 1; + uint64_t pm_slv_winkle_fence : 1; + uint64_t tp_tc_dpll_testmode_dc : 1; + uint64_t block_all_wakeup_sources : 1; + uint64_t thold_timer_sel : 2; + uint64_t tp_clkglm_const_dc : 1; + uint64_t tp_clkglm_core_sel_dc : 2; + uint64_t special_wkup_done : 1; + uint64_t tp_clkglm_eco_sel_dc : 1; + uint64_t tp_clkglm_sel_dc : 3; + uint64_t tp_clk_async_reset_dc : 3; + uint64_t chksw_hw257424_disable : 1; + uint64_t tp_tc_pervasive_eco_fence : 1; + uint64_t tp_tc_core2cache_fence : 1; + uint64_t tp_tc_cache2core_fence : 1; + uint64_t dpll_testout_ctl : 8; + uint64_t pmgp0_spare_bit11 : 1; + uint64_t dpll_reset : 1; + uint64_t pmgp0_spare2 : 1; + uint64_t dpll_lock_sense : 1; + uint64_t pm_dpll_timer_ena : 1; + uint64_t cpm_cal_set_val : 1; + uint64_t cpm_cal_set_override_en : 1; + uint64_t perv_thold : 1; + uint64_t dpll_thold : 1; + uint64_t tp_tc_restart_core_domain : 1; + uint64_t pmgp0_spare_bit1 : 1; + uint64_t pm_disable : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmgp0_reg_and_t; + + + +typedef union pcbs_pmgp0_reg_or { + + 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 pm_disable : 1; + uint64_t pmgp0_spare_bit1 : 1; + uint64_t tp_tc_restart_core_domain : 1; + uint64_t dpll_thold : 1; + uint64_t perv_thold : 1; + uint64_t cpm_cal_set_override_en : 1; + uint64_t cpm_cal_set_val : 1; + uint64_t pm_dpll_timer_ena : 1; + uint64_t dpll_lock_sense : 1; + uint64_t pmgp0_spare2 : 1; + uint64_t dpll_reset : 1; + uint64_t pmgp0_spare_bit11 : 1; + uint64_t dpll_testout_ctl : 8; + uint64_t tp_tc_cache2core_fence : 1; + uint64_t tp_tc_core2cache_fence : 1; + uint64_t tp_tc_pervasive_eco_fence : 1; + uint64_t chksw_hw257424_disable : 1; + uint64_t tp_clk_async_reset_dc : 3; + uint64_t tp_clkglm_sel_dc : 3; + uint64_t tp_clkglm_eco_sel_dc : 1; + uint64_t special_wkup_done : 1; + uint64_t tp_clkglm_core_sel_dc : 2; + uint64_t tp_clkglm_const_dc : 1; + uint64_t thold_timer_sel : 2; + uint64_t block_all_wakeup_sources : 1; + uint64_t tp_tc_dpll_testmode_dc : 1; + uint64_t pm_slv_winkle_fence : 1; + uint64_t l3_enable_switch : 1; + uint64_t tp_cplt_ivrm_refbypass_dc : 1; + uint64_t chksw_hw241939_disable : 1; + uint64_t chksw_hw273115_disable : 1; + uint64_t chksw_hw245103_disable : 1; + uint64_t chksw_hw257534_disable : 1; + uint64_t chksw_hw259509_enable : 1; + uint64_t pmgp0_spare3 : 1; + uint64_t wakeup_int_type : 2; + uint64_t dpll_lock : 1; + uint64_t special_wkup_all_sources_ored : 1; + uint64_t regular_wkup_available : 1; + uint64_t block_reg_wkup_sources : 1; + uint64_t _reserved0 : 10; +#else + uint64_t _reserved0 : 10; + uint64_t block_reg_wkup_sources : 1; + uint64_t regular_wkup_available : 1; + uint64_t special_wkup_all_sources_ored : 1; + uint64_t dpll_lock : 1; + uint64_t wakeup_int_type : 2; + uint64_t pmgp0_spare3 : 1; + uint64_t chksw_hw259509_enable : 1; + uint64_t chksw_hw257534_disable : 1; + uint64_t chksw_hw245103_disable : 1; + uint64_t chksw_hw273115_disable : 1; + uint64_t chksw_hw241939_disable : 1; + uint64_t tp_cplt_ivrm_refbypass_dc : 1; + uint64_t l3_enable_switch : 1; + uint64_t pm_slv_winkle_fence : 1; + uint64_t tp_tc_dpll_testmode_dc : 1; + uint64_t block_all_wakeup_sources : 1; + uint64_t thold_timer_sel : 2; + uint64_t tp_clkglm_const_dc : 1; + uint64_t tp_clkglm_core_sel_dc : 2; + uint64_t special_wkup_done : 1; + uint64_t tp_clkglm_eco_sel_dc : 1; + uint64_t tp_clkglm_sel_dc : 3; + uint64_t tp_clk_async_reset_dc : 3; + uint64_t chksw_hw257424_disable : 1; + uint64_t tp_tc_pervasive_eco_fence : 1; + uint64_t tp_tc_core2cache_fence : 1; + uint64_t tp_tc_cache2core_fence : 1; + uint64_t dpll_testout_ctl : 8; + uint64_t pmgp0_spare_bit11 : 1; + uint64_t dpll_reset : 1; + uint64_t pmgp0_spare2 : 1; + uint64_t dpll_lock_sense : 1; + uint64_t pm_dpll_timer_ena : 1; + uint64_t cpm_cal_set_val : 1; + uint64_t cpm_cal_set_override_en : 1; + uint64_t perv_thold : 1; + uint64_t dpll_thold : 1; + uint64_t tp_tc_restart_core_domain : 1; + uint64_t pmgp0_spare_bit1 : 1; + uint64_t pm_disable : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmgp0_reg_or_t; + + + +typedef union pcbs_pmgp1_reg { + + 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 sleep_power_down_en : 1; + uint64_t sleep_power_up_en : 1; + uint64_t sleep_power_off_sel : 1; + uint64_t winkle_power_down_en : 1; + uint64_t winkle_power_up_en : 1; + uint64_t winkle_power_off_sel : 1; + uint64_t oha_wkup_override_en : 1; + uint64_t oha_pm_wkup_override : 1; + uint64_t oha_spc_wkup_override : 1; + uint64_t endp_reset_pm_only : 1; + uint64_t dpll_freq_override_enable : 1; + uint64_t pm_spr_override_en : 1; + uint64_t force_safe_mode : 1; + uint64_t ivrm_safe_mode_en : 1; + uint64_t ivrm_safe_mode_force_active : 1; + uint64_t pmicr_latency_en : 1; + uint64_t enable_occ_ctrl_for_local_pstate_eff_req : 1; + uint64_t serialize_pfet_powerdown : 1; + uint64_t serialize_pfet_powerup : 1; + uint64_t disable_force_deep_to_fast_sleep : 1; + uint64_t disable_force_deep_to_fast_winkle : 1; + uint64_t _reserved0 : 43; +#else + uint64_t _reserved0 : 43; + uint64_t disable_force_deep_to_fast_winkle : 1; + uint64_t disable_force_deep_to_fast_sleep : 1; + uint64_t serialize_pfet_powerup : 1; + uint64_t serialize_pfet_powerdown : 1; + uint64_t enable_occ_ctrl_for_local_pstate_eff_req : 1; + uint64_t pmicr_latency_en : 1; + uint64_t ivrm_safe_mode_force_active : 1; + uint64_t ivrm_safe_mode_en : 1; + uint64_t force_safe_mode : 1; + uint64_t pm_spr_override_en : 1; + uint64_t dpll_freq_override_enable : 1; + uint64_t endp_reset_pm_only : 1; + uint64_t oha_spc_wkup_override : 1; + uint64_t oha_pm_wkup_override : 1; + uint64_t oha_wkup_override_en : 1; + uint64_t winkle_power_off_sel : 1; + uint64_t winkle_power_up_en : 1; + uint64_t winkle_power_down_en : 1; + uint64_t sleep_power_off_sel : 1; + uint64_t sleep_power_up_en : 1; + uint64_t sleep_power_down_en : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmgp1_reg_t; + + + +typedef union pcbs_pmgp1_reg_and { + + 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 sleep_power_down_en : 1; + uint64_t sleep_power_up_en : 1; + uint64_t sleep_power_off_sel : 1; + uint64_t winkle_power_down_en : 1; + uint64_t winkle_power_up_en : 1; + uint64_t winkle_power_off_sel : 1; + uint64_t oha_wkup_override_en : 1; + uint64_t oha_pm_wkup_override : 1; + uint64_t oha_spc_wkup_override : 1; + uint64_t endp_reset_pm_only : 1; + uint64_t dpll_freq_override_enable : 1; + uint64_t pm_spr_override_en : 1; + uint64_t force_safe_mode : 1; + uint64_t ivrm_safe_mode_en : 1; + uint64_t ivrm_safe_mode_force_active : 1; + uint64_t pmicr_latency_en : 1; + uint64_t enable_occ_ctrl_for_local_pstate_eff_req : 1; + uint64_t serialize_pfet_powerdown : 1; + uint64_t serialize_pfet_powerup : 1; + uint64_t disable_force_deep_to_fast_sleep : 1; + uint64_t disable_force_deep_to_fast_winkle : 1; + uint64_t _reserved0 : 43; +#else + uint64_t _reserved0 : 43; + uint64_t disable_force_deep_to_fast_winkle : 1; + uint64_t disable_force_deep_to_fast_sleep : 1; + uint64_t serialize_pfet_powerup : 1; + uint64_t serialize_pfet_powerdown : 1; + uint64_t enable_occ_ctrl_for_local_pstate_eff_req : 1; + uint64_t pmicr_latency_en : 1; + uint64_t ivrm_safe_mode_force_active : 1; + uint64_t ivrm_safe_mode_en : 1; + uint64_t force_safe_mode : 1; + uint64_t pm_spr_override_en : 1; + uint64_t dpll_freq_override_enable : 1; + uint64_t endp_reset_pm_only : 1; + uint64_t oha_spc_wkup_override : 1; + uint64_t oha_pm_wkup_override : 1; + uint64_t oha_wkup_override_en : 1; + uint64_t winkle_power_off_sel : 1; + uint64_t winkle_power_up_en : 1; + uint64_t winkle_power_down_en : 1; + uint64_t sleep_power_off_sel : 1; + uint64_t sleep_power_up_en : 1; + uint64_t sleep_power_down_en : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmgp1_reg_and_t; + + + +typedef union pcbs_pmgp1_reg_or { + + 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 sleep_power_down_en : 1; + uint64_t sleep_power_up_en : 1; + uint64_t sleep_power_off_sel : 1; + uint64_t winkle_power_down_en : 1; + uint64_t winkle_power_up_en : 1; + uint64_t winkle_power_off_sel : 1; + uint64_t oha_wkup_override_en : 1; + uint64_t oha_pm_wkup_override : 1; + uint64_t oha_spc_wkup_override : 1; + uint64_t endp_reset_pm_only : 1; + uint64_t dpll_freq_override_enable : 1; + uint64_t pm_spr_override_en : 1; + uint64_t force_safe_mode : 1; + uint64_t ivrm_safe_mode_en : 1; + uint64_t ivrm_safe_mode_force_active : 1; + uint64_t pmicr_latency_en : 1; + uint64_t enable_occ_ctrl_for_local_pstate_eff_req : 1; + uint64_t serialize_pfet_powerdown : 1; + uint64_t serialize_pfet_powerup : 1; + uint64_t disable_force_deep_to_fast_sleep : 1; + uint64_t disable_force_deep_to_fast_winkle : 1; + uint64_t _reserved0 : 43; +#else + uint64_t _reserved0 : 43; + uint64_t disable_force_deep_to_fast_winkle : 1; + uint64_t disable_force_deep_to_fast_sleep : 1; + uint64_t serialize_pfet_powerup : 1; + uint64_t serialize_pfet_powerdown : 1; + uint64_t enable_occ_ctrl_for_local_pstate_eff_req : 1; + uint64_t pmicr_latency_en : 1; + uint64_t ivrm_safe_mode_force_active : 1; + uint64_t ivrm_safe_mode_en : 1; + uint64_t force_safe_mode : 1; + uint64_t pm_spr_override_en : 1; + uint64_t dpll_freq_override_enable : 1; + uint64_t endp_reset_pm_only : 1; + uint64_t oha_spc_wkup_override : 1; + uint64_t oha_pm_wkup_override : 1; + uint64_t oha_wkup_override_en : 1; + uint64_t winkle_power_off_sel : 1; + uint64_t winkle_power_up_en : 1; + uint64_t winkle_power_down_en : 1; + uint64_t sleep_power_off_sel : 1; + uint64_t sleep_power_up_en : 1; + uint64_t sleep_power_down_en : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmgp1_reg_or_t; + + + +typedef union pcbs_pfvddcntlstat_reg { + + 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 core_vdd_pfet_force_state : 2; + uint64_t eco_vdd_pfet_force_state : 2; + uint64_t core_vdd_pfet_val_override : 1; + uint64_t core_vdd_pfet_sel_override : 1; + uint64_t eco_vdd_pfet_val_override : 1; + uint64_t eco_vdd_pfet_sel_override : 1; + uint64_t core_vdd_pfet_enable_regulation_finger : 1; + uint64_t eco_vdd_pfet_enable_regulation_finger : 1; + uint64_t core_vdd_pfet_enable_value : 12; + uint64_t core_vdd_pfet_sel_value : 4; + uint64_t eco_vdd_pfet_enable_value : 12; + uint64_t eco_vdd_pfet_sel_value : 4; + uint64_t core_vdd_pg_state : 4; + uint64_t core_vdd_pg_sel : 4; + uint64_t eco_vdd_pg_state : 4; + uint64_t eco_vdd_pg_sel : 4; + uint64_t _reserved0 : 6; +#else + uint64_t _reserved0 : 6; + uint64_t eco_vdd_pg_sel : 4; + uint64_t eco_vdd_pg_state : 4; + uint64_t core_vdd_pg_sel : 4; + uint64_t core_vdd_pg_state : 4; + uint64_t eco_vdd_pfet_sel_value : 4; + uint64_t eco_vdd_pfet_enable_value : 12; + uint64_t core_vdd_pfet_sel_value : 4; + uint64_t core_vdd_pfet_enable_value : 12; + uint64_t eco_vdd_pfet_enable_regulation_finger : 1; + uint64_t core_vdd_pfet_enable_regulation_finger : 1; + uint64_t eco_vdd_pfet_sel_override : 1; + uint64_t eco_vdd_pfet_val_override : 1; + uint64_t core_vdd_pfet_sel_override : 1; + uint64_t core_vdd_pfet_val_override : 1; + uint64_t eco_vdd_pfet_force_state : 2; + uint64_t core_vdd_pfet_force_state : 2; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pfvddcntlstat_reg_t; + + + +typedef union pcbs_pfvcscntlstat_reg { + + 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 core_vcs_pfet_force_state : 2; + uint64_t eco_vcs_pfet_force_state : 2; + uint64_t core_vcs_pfet_val_override : 1; + uint64_t core_vcs_pfet_sel_override : 1; + uint64_t eco_vcs_pfet_val_override : 1; + uint64_t eco_vcs_pfet_sel_override : 1; + uint64_t core_vcs_pfet_enable_regulation_finger : 1; + uint64_t eco_vcs_pfet_enable_regulation_finger : 1; + uint64_t core_vcs_pfet_enable_value : 12; + uint64_t core_vcs_pfet_sel_value : 4; + uint64_t eco_vcs_pfet_enable_value : 12; + uint64_t eco_vcs_pfet_sel_value : 4; + uint64_t core_vcs_pg_state : 4; + uint64_t core_vcs_pg_sel : 4; + uint64_t eco_vcs_pg_state : 4; + uint64_t eco_vcs_pg_sel : 4; + uint64_t _reserved0 : 6; +#else + uint64_t _reserved0 : 6; + uint64_t eco_vcs_pg_sel : 4; + uint64_t eco_vcs_pg_state : 4; + uint64_t core_vcs_pg_sel : 4; + uint64_t core_vcs_pg_state : 4; + uint64_t eco_vcs_pfet_sel_value : 4; + uint64_t eco_vcs_pfet_enable_value : 12; + uint64_t core_vcs_pfet_sel_value : 4; + uint64_t core_vcs_pfet_enable_value : 12; + uint64_t eco_vcs_pfet_enable_regulation_finger : 1; + uint64_t core_vcs_pfet_enable_regulation_finger : 1; + uint64_t eco_vcs_pfet_sel_override : 1; + uint64_t eco_vcs_pfet_val_override : 1; + uint64_t core_vcs_pfet_sel_override : 1; + uint64_t core_vcs_pfet_val_override : 1; + uint64_t eco_vcs_pfet_force_state : 2; + uint64_t core_vcs_pfet_force_state : 2; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pfvcscntlstat_reg_t; + + + +typedef union pcbs_pfsense_reg { + + 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 tp_core_vdd_pfet_enable_sense : 12; + uint64_t tp_eco_vdd_pfet_enable_sense : 12; + uint64_t tp_core_vcs_pfet_enable_sense : 12; + uint64_t tp_eco_vcs_pfet_enable_sense : 12; + uint64_t _reserved0 : 16; +#else + uint64_t _reserved0 : 16; + uint64_t tp_eco_vcs_pfet_enable_sense : 12; + uint64_t tp_core_vcs_pfet_enable_sense : 12; + uint64_t tp_eco_vdd_pfet_enable_sense : 12; + uint64_t tp_core_vdd_pfet_enable_sense : 12; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pfsense_reg_t; + + + +typedef union pcbs_pmerrsum_reg { + + 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 pm_error : 1; + uint64_t _reserved0 : 63; +#else + uint64_t _reserved0 : 63; + uint64_t pm_error : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmerrsum_reg_t; + + + +typedef union pcbs_pmerr_reg { + + 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 pcbs_sleep_entry_notify_pmc_hang_err : 1; + uint64_t pcbs_sleep_entry_notify_pmc_assist_hang_err : 1; + uint64_t pcbs_sleep_entry_notify_pmc_err : 1; + uint64_t pcbs_sleep_exit_invoke_pore_err : 1; + uint64_t pcbs_winkle_entry_notify_pmc_err : 1; + uint64_t pcbs_winkle_entry_send_int_assist_err : 1; + uint64_t pcbs_winkle_exit_notify_pmc_err : 1; + uint64_t pcbs_wait_dpll_lock_err : 1; + uint64_t pcbs_spare8_err : 1; + uint64_t pcbs_winkle_exit_send_int_assist_err : 1; + uint64_t pcbs_winkle_exit_send_int_powup_assist_err : 1; + uint64_t pcbs_write_fsm_goto_reg_in_invalid_state_err : 1; + uint64_t pcbs_write_pmgp0_in_invalid_state_err : 1; + uint64_t pcbs_freq_overflow_in_pstate_mode_err : 1; + uint64_t pcbs_eco_rs_bypass_confusion_err : 1; + uint64_t pcbs_core_rs_bypass_confusion_err : 1; + uint64_t pcbs_read_lpst_in_pstate_mode_err : 1; + uint64_t pcbs_lpst_read_corr_err : 1; + uint64_t pcbs_lpst_read_uncorr_err : 1; + uint64_t pcbs_pfet_strength_overflow_err : 1; + uint64_t pcbs_vds_lookup_err : 1; + uint64_t pcbs_idle_interrupt_timeout_err : 1; + uint64_t pcbs_pstate_interrupt_timeout_err : 1; + uint64_t pcbs_global_actual_sync_interrupt_timeout_err : 1; + uint64_t pcbs_pmax_sync_interrupt_timeout_err : 1; + uint64_t pcbs_global_actual_pstate_protocol_err : 1; + uint64_t pcbs_pmax_protocol_err : 1; + uint64_t pcbs_ivrm_gross_or_fine_err : 1; + uint64_t pcbs_ivrm_range_err : 1; + uint64_t pcbs_dpll_cpm_fmin_err : 1; + uint64_t pcbs_dpll_dco_full_err : 1; + uint64_t pcbs_dpll_dco_empty_err : 1; + uint64_t pcbs_dpll_int_err : 1; + uint64_t pcbs_fmin_and_not_cpmbit_err : 1; + uint64_t pcbs_dpll_faster_than_fmax_plus_delta1_err : 1; + uint64_t pcbs_dpll_slower_than_fmin_minus_delta2_err : 1; + uint64_t pcbs_resclk_csb_instr_vector_chg_in_invalid_state_err : 1; + uint64_t pcbs_reslkc_band_boundary_chg_in_invalid_state_err : 1; + uint64_t pcbs_occ_heartbeat_loss_err : 1; + uint64_t pcbs_spare39_err : 1; + uint64_t pcbs_spare40_err : 1; + uint64_t pcbs_spare41_err : 1; + uint64_t pcbs_spare42_err : 1; + uint64_t _reserved0 : 21; +#else + uint64_t _reserved0 : 21; + uint64_t pcbs_spare42_err : 1; + uint64_t pcbs_spare41_err : 1; + uint64_t pcbs_spare40_err : 1; + uint64_t pcbs_spare39_err : 1; + uint64_t pcbs_occ_heartbeat_loss_err : 1; + uint64_t pcbs_reslkc_band_boundary_chg_in_invalid_state_err : 1; + uint64_t pcbs_resclk_csb_instr_vector_chg_in_invalid_state_err : 1; + uint64_t pcbs_dpll_slower_than_fmin_minus_delta2_err : 1; + uint64_t pcbs_dpll_faster_than_fmax_plus_delta1_err : 1; + uint64_t pcbs_fmin_and_not_cpmbit_err : 1; + uint64_t pcbs_dpll_int_err : 1; + uint64_t pcbs_dpll_dco_empty_err : 1; + uint64_t pcbs_dpll_dco_full_err : 1; + uint64_t pcbs_dpll_cpm_fmin_err : 1; + uint64_t pcbs_ivrm_range_err : 1; + uint64_t pcbs_ivrm_gross_or_fine_err : 1; + uint64_t pcbs_pmax_protocol_err : 1; + uint64_t pcbs_global_actual_pstate_protocol_err : 1; + uint64_t pcbs_pmax_sync_interrupt_timeout_err : 1; + uint64_t pcbs_global_actual_sync_interrupt_timeout_err : 1; + uint64_t pcbs_pstate_interrupt_timeout_err : 1; + uint64_t pcbs_idle_interrupt_timeout_err : 1; + uint64_t pcbs_vds_lookup_err : 1; + uint64_t pcbs_pfet_strength_overflow_err : 1; + uint64_t pcbs_lpst_read_uncorr_err : 1; + uint64_t pcbs_lpst_read_corr_err : 1; + uint64_t pcbs_read_lpst_in_pstate_mode_err : 1; + uint64_t pcbs_core_rs_bypass_confusion_err : 1; + uint64_t pcbs_eco_rs_bypass_confusion_err : 1; + uint64_t pcbs_freq_overflow_in_pstate_mode_err : 1; + uint64_t pcbs_write_pmgp0_in_invalid_state_err : 1; + uint64_t pcbs_write_fsm_goto_reg_in_invalid_state_err : 1; + uint64_t pcbs_winkle_exit_send_int_powup_assist_err : 1; + uint64_t pcbs_winkle_exit_send_int_assist_err : 1; + uint64_t pcbs_spare8_err : 1; + uint64_t pcbs_wait_dpll_lock_err : 1; + uint64_t pcbs_winkle_exit_notify_pmc_err : 1; + uint64_t pcbs_winkle_entry_send_int_assist_err : 1; + uint64_t pcbs_winkle_entry_notify_pmc_err : 1; + uint64_t pcbs_sleep_exit_invoke_pore_err : 1; + uint64_t pcbs_sleep_entry_notify_pmc_err : 1; + uint64_t pcbs_sleep_entry_notify_pmc_assist_hang_err : 1; + uint64_t pcbs_sleep_entry_notify_pmc_hang_err : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmerr_reg_t; + + + +typedef union pcbs_pmerrmask_reg { + + 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 pcbs_sleep_entry_notify_pmc_hang_err_mask : 1; + uint64_t pcbs_sleep_entry_notify_pmc_assist_hang_err_mask : 1; + uint64_t pcbs_sleep_entry_notify_pmc_err_mask : 1; + uint64_t pcbs_sleep_exit_invoke_pore_err_mask : 1; + uint64_t pcbs_winkle_entry_notify_pmc_err_mask : 1; + uint64_t pcbs_winkle_entry_send_int_assist_err_mask : 1; + uint64_t pcbs_winkle_exit_notify_pmc_err_mask : 1; + uint64_t pcbs_wait_dpll_lock_err_mask : 1; + uint64_t pcbs_spare8_err_mask : 1; + uint64_t pcbs_winkle_exit_send_int_assist_err_mask : 1; + uint64_t pcbs_winkle_exit_send_int_powup_assist_err_mask : 1; + uint64_t pcbs_write_fsm_goto_reg_in_invalid_state_err_mask : 1; + uint64_t pcbs_write_pmgp0_in_invalid_state_err_mask : 1; + uint64_t pcbs_freq_overflow_in_pstate_mode_err_mask : 1; + uint64_t pcbs_eco_rs_bypass_confusion_err_mask : 1; + uint64_t pcbs_core_rs_bypass_confusion_err_mask : 1; + uint64_t pcbs_read_lpst_in_pstate_mode_err_mask : 1; + uint64_t pcbs_lpst_read_corr_err_mask : 1; + uint64_t pcbs_lpst_read_uncorr_err_mask : 1; + uint64_t pcbs_pfet_strength_overflow_err_mask : 1; + uint64_t pcbs_vds_lookup_err_mask : 1; + uint64_t pcbs_idle_interrupt_timeout_err_mask : 1; + uint64_t pcbs_pstate_interrupt_timeout_err_mask : 1; + uint64_t pcbs_global_actual_sync_interrupt_timeout_err_mask : 1; + uint64_t pcbs_pmax_sync_interrupt_timeout_err_mask : 1; + uint64_t pcbs_global_actual_pstate_protocol_err_mask : 1; + uint64_t pcbs_pmax_protocol_err_mask : 1; + uint64_t pcbs_ivrm_gross_or_fine_err_mask : 1; + uint64_t pcbs_ivrm_range_err_mask : 1; + uint64_t pcbs_dpll_cpm_fmin_err_mask : 1; + uint64_t pcbs_dpll_dco_full_err_mask : 1; + uint64_t pcbs_dpll_dco_empty_err_mask : 1; + uint64_t pcbs_dpll_int_err_mask : 1; + uint64_t pcbs_fmin_and_not_cpmbit_err_mask : 1; + uint64_t pcbs_dpll_faster_than_fmax_plus_delta1_err_mask : 1; + uint64_t pcbs_dpll_slower_than_fmin_minus_delta2_err_mask : 1; + uint64_t pcbs_resclk_csb_instr_vector_chg_in_invalid_state_err_mask : 1; + uint64_t pcbs_reslkc_band_boundary_chg_in_invalid_state_err_mask : 1; + uint64_t pcbs_occ_heartbeat_loss_err_mask : 1; + uint64_t pcbs_spare39_err_mask : 1; + uint64_t pcbs_spare40_err_mask : 1; + uint64_t pcbs_spare41_err_mask : 1; + uint64_t pcbs_spare42_err_mask : 1; + uint64_t _reserved0 : 21; +#else + uint64_t _reserved0 : 21; + uint64_t pcbs_spare42_err_mask : 1; + uint64_t pcbs_spare41_err_mask : 1; + uint64_t pcbs_spare40_err_mask : 1; + uint64_t pcbs_spare39_err_mask : 1; + uint64_t pcbs_occ_heartbeat_loss_err_mask : 1; + uint64_t pcbs_reslkc_band_boundary_chg_in_invalid_state_err_mask : 1; + uint64_t pcbs_resclk_csb_instr_vector_chg_in_invalid_state_err_mask : 1; + uint64_t pcbs_dpll_slower_than_fmin_minus_delta2_err_mask : 1; + uint64_t pcbs_dpll_faster_than_fmax_plus_delta1_err_mask : 1; + uint64_t pcbs_fmin_and_not_cpmbit_err_mask : 1; + uint64_t pcbs_dpll_int_err_mask : 1; + uint64_t pcbs_dpll_dco_empty_err_mask : 1; + uint64_t pcbs_dpll_dco_full_err_mask : 1; + uint64_t pcbs_dpll_cpm_fmin_err_mask : 1; + uint64_t pcbs_ivrm_range_err_mask : 1; + uint64_t pcbs_ivrm_gross_or_fine_err_mask : 1; + uint64_t pcbs_pmax_protocol_err_mask : 1; + uint64_t pcbs_global_actual_pstate_protocol_err_mask : 1; + uint64_t pcbs_pmax_sync_interrupt_timeout_err_mask : 1; + uint64_t pcbs_global_actual_sync_interrupt_timeout_err_mask : 1; + uint64_t pcbs_pstate_interrupt_timeout_err_mask : 1; + uint64_t pcbs_idle_interrupt_timeout_err_mask : 1; + uint64_t pcbs_vds_lookup_err_mask : 1; + uint64_t pcbs_pfet_strength_overflow_err_mask : 1; + uint64_t pcbs_lpst_read_uncorr_err_mask : 1; + uint64_t pcbs_lpst_read_corr_err_mask : 1; + uint64_t pcbs_read_lpst_in_pstate_mode_err_mask : 1; + uint64_t pcbs_core_rs_bypass_confusion_err_mask : 1; + uint64_t pcbs_eco_rs_bypass_confusion_err_mask : 1; + uint64_t pcbs_freq_overflow_in_pstate_mode_err_mask : 1; + uint64_t pcbs_write_pmgp0_in_invalid_state_err_mask : 1; + uint64_t pcbs_write_fsm_goto_reg_in_invalid_state_err_mask : 1; + uint64_t pcbs_winkle_exit_send_int_powup_assist_err_mask : 1; + uint64_t pcbs_winkle_exit_send_int_assist_err_mask : 1; + uint64_t pcbs_spare8_err_mask : 1; + uint64_t pcbs_wait_dpll_lock_err_mask : 1; + uint64_t pcbs_winkle_exit_notify_pmc_err_mask : 1; + uint64_t pcbs_winkle_entry_send_int_assist_err_mask : 1; + uint64_t pcbs_winkle_entry_notify_pmc_err_mask : 1; + uint64_t pcbs_sleep_exit_invoke_pore_err_mask : 1; + uint64_t pcbs_sleep_entry_notify_pmc_err_mask : 1; + uint64_t pcbs_sleep_entry_notify_pmc_assist_hang_err_mask : 1; + uint64_t pcbs_sleep_entry_notify_pmc_hang_err_mask : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmerrmask_reg_t; + + + +typedef union pcbs_pmspcwkupfsp_reg { + + 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 fsp_special_wakeup : 1; + uint64_t _reserved0 : 63; +#else + uint64_t _reserved0 : 63; + uint64_t fsp_special_wakeup : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmspcwkupfsp_reg_t; + + + +typedef union pcbs_pmspcwkupocc_reg { + + 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 occ_special_wakeup : 1; + uint64_t _reserved0 : 63; +#else + uint64_t _reserved0 : 63; + uint64_t occ_special_wakeup : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmspcwkupocc_reg_t; + + + +typedef union pcbs_pmspcwkupphyp_reg { + + 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 phyp_special_wakeup : 1; + uint64_t _reserved0 : 63; +#else + uint64_t _reserved0 : 63; + uint64_t phyp_special_wakeup : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmspcwkupphyp_reg_t; + + + +typedef union pcbs_pmstatehistphyp_reg { + + 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 phyp_pm_state : 3; + uint64_t phyp_past_core_instruct_stop : 1; + uint64_t phyp_past_core_clk_stop : 1; + uint64_t phyp_past_core_pwr_off : 1; + uint64_t phyp_past_eco_clk_stop : 1; + uint64_t phyp_past_eco_pwr_off : 1; + uint64_t _reserved0 : 56; +#else + uint64_t _reserved0 : 56; + uint64_t phyp_past_eco_pwr_off : 1; + uint64_t phyp_past_eco_clk_stop : 1; + uint64_t phyp_past_core_pwr_off : 1; + uint64_t phyp_past_core_clk_stop : 1; + uint64_t phyp_past_core_instruct_stop : 1; + uint64_t phyp_pm_state : 3; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmstatehistphyp_reg_t; + + + +typedef union pcbs_pmstatehistfsp_reg { + + 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 fsp_pm_state : 3; + uint64_t fsp_past_core_instruct_stop : 1; + uint64_t fsp_past_core_clk_stop : 1; + uint64_t fsp_past_core_pwr_off : 1; + uint64_t fsp_past_eco_clk_stop : 1; + uint64_t fsp_past_eco_pwr_off : 1; + uint64_t _reserved0 : 56; +#else + uint64_t _reserved0 : 56; + uint64_t fsp_past_eco_pwr_off : 1; + uint64_t fsp_past_eco_clk_stop : 1; + uint64_t fsp_past_core_pwr_off : 1; + uint64_t fsp_past_core_clk_stop : 1; + uint64_t fsp_past_core_instruct_stop : 1; + uint64_t fsp_pm_state : 3; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmstatehistfsp_reg_t; + + + +typedef union pcbs_pmstatehistocc_reg { + + 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 occ_pm_state : 3; + uint64_t occ_past_core_instruct_stop : 1; + uint64_t occ_past_core_clk_stop : 1; + uint64_t occ_past_core_pwr_off : 1; + uint64_t occ_past_eco_clk_stop : 1; + uint64_t occ_past_eco_pwr_off : 1; + uint64_t _reserved0 : 56; +#else + uint64_t _reserved0 : 56; + uint64_t occ_past_eco_pwr_off : 1; + uint64_t occ_past_eco_clk_stop : 1; + uint64_t occ_past_core_pwr_off : 1; + uint64_t occ_past_core_clk_stop : 1; + uint64_t occ_past_core_instruct_stop : 1; + uint64_t occ_pm_state : 3; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmstatehistocc_reg_t; + + + +typedef union pcbs_pmstatehistperf_reg { + + 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 perf_pm_state : 3; + uint64_t perf_past_core_instruct_stop : 1; + uint64_t perf_past_core_clk_stop : 1; + uint64_t perf_past_core_pwr_off : 1; + uint64_t perf_past_eco_clk_stop : 1; + uint64_t perf_past_eco_pwr_off : 1; + uint64_t _reserved0 : 56; +#else + uint64_t _reserved0 : 56; + uint64_t perf_past_eco_pwr_off : 1; + uint64_t perf_past_eco_clk_stop : 1; + uint64_t perf_past_core_pwr_off : 1; + uint64_t perf_past_core_clk_stop : 1; + uint64_t perf_past_core_instruct_stop : 1; + uint64_t perf_pm_state : 3; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmstatehistperf_reg_t; + + + +typedef union pcbs_idlefsmgotocmd_reg { + + 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 idle_fsm_goto_cmd : 2; + uint64_t babystp_trigger_sleep_entry : 1; + uint64_t babystp_trigger_winkle_entry : 1; + uint64_t babystp_trigger_wakeup : 1; + uint64_t _reserved0 : 59; +#else + uint64_t _reserved0 : 59; + uint64_t babystp_trigger_wakeup : 1; + uint64_t babystp_trigger_winkle_entry : 1; + uint64_t babystp_trigger_sleep_entry : 1; + uint64_t idle_fsm_goto_cmd : 2; +#endif // _BIG_ENDIAN + } fields; +} pcbs_idlefsmgotocmd_reg_t; + + + +typedef union pcbs_corepfpudly_reg { + + 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 core_powup_dly0 : 4; + uint64_t core_powup_dly1 : 4; + uint64_t core_power_up_delay_sel : 12; + uint64_t _reserved0 : 44; +#else + uint64_t _reserved0 : 44; + uint64_t core_power_up_delay_sel : 12; + uint64_t core_powup_dly1 : 4; + uint64_t core_powup_dly0 : 4; +#endif // _BIG_ENDIAN + } fields; +} pcbs_corepfpudly_reg_t; + + + +typedef union pcbs_corepfpddly_reg { + + 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 core_powdn_dly0 : 4; + uint64_t core_powdn_dly1 : 4; + uint64_t core_power_dn_delay_sel : 12; + uint64_t _reserved0 : 44; +#else + uint64_t _reserved0 : 44; + uint64_t core_power_dn_delay_sel : 12; + uint64_t core_powdn_dly1 : 4; + uint64_t core_powdn_dly0 : 4; +#endif // _BIG_ENDIAN + } fields; +} pcbs_corepfpddly_reg_t; + + + +typedef union pcbs_corepfvret_reg { + + 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 core_vret_sel : 4; + uint64_t core_voff_sel : 4; + uint64_t _reserved0 : 56; +#else + uint64_t _reserved0 : 56; + uint64_t core_voff_sel : 4; + uint64_t core_vret_sel : 4; +#endif // _BIG_ENDIAN + } fields; +} pcbs_corepfvret_reg_t; + + + +typedef union pcbs_ecopfpudly_reg { + + 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 eco_powup_dly0 : 4; + uint64_t eco_powup_dly1 : 4; + uint64_t eco_power_up_delay_sel : 12; + uint64_t _reserved0 : 44; +#else + uint64_t _reserved0 : 44; + uint64_t eco_power_up_delay_sel : 12; + uint64_t eco_powup_dly1 : 4; + uint64_t eco_powup_dly0 : 4; +#endif // _BIG_ENDIAN + } fields; +} pcbs_ecopfpudly_reg_t; + + + +typedef union pcbs_ecopfpddly_reg { + + 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 eco_powdn_dly0 : 4; + uint64_t eco_powdn_dly1 : 4; + uint64_t eco_power_dn_delay_sel : 12; + uint64_t _reserved0 : 44; +#else + uint64_t _reserved0 : 44; + uint64_t eco_power_dn_delay_sel : 12; + uint64_t eco_powdn_dly1 : 4; + uint64_t eco_powdn_dly0 : 4; +#endif // _BIG_ENDIAN + } fields; +} pcbs_ecopfpddly_reg_t; + + + +typedef union pcbs_ecopfvret_reg { + + 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 eco_vret_sel : 4; + uint64_t eco_voff_sel : 4; + uint64_t _reserved0 : 56; +#else + uint64_t _reserved0 : 56; + uint64_t eco_voff_sel : 4; + uint64_t eco_vret_sel : 4; +#endif // _BIG_ENDIAN + } fields; +} pcbs_ecopfvret_reg_t; + + + +typedef union pcbs_freq_ctrl_reg { + + 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 dpll_fmin : 9; + uint64_t dpll_fmax : 9; + uint64_t dpll_fmax_bias : 4; + uint64_t frequ_at_pstate0 : 9; + uint64_t _reserved0 : 33; +#else + uint64_t _reserved0 : 33; + uint64_t frequ_at_pstate0 : 9; + uint64_t dpll_fmax_bias : 4; + uint64_t dpll_fmax : 9; + uint64_t dpll_fmin : 9; +#endif // _BIG_ENDIAN + } fields; +} pcbs_freq_ctrl_reg_t; + + + +typedef union pcbs_dpll_cpm_parm_reg { + + 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 lf_slewratexpi : 8; + uint64_t lf_use_cpmxpi : 1; + uint64_t ff_use_cpmxpi : 1; + uint64_t cpm_filter_enable : 1; + uint64_t ff_bypassxpi : 1; + uint64_t dco_override : 1; + uint64_t dco_incr : 1; + uint64_t dco_decr : 1; + uint64_t dpll_lock_timer_replacement_value : 9; + uint64_t pre_vret_pstate : 8; + uint64_t override_pcbs_dpll_synchronizer : 1; + uint64_t dpll_char_delta1 : 4; + uint64_t dpll_char_delta2 : 4; + uint64_t _reserved0 : 23; +#else + uint64_t _reserved0 : 23; + uint64_t dpll_char_delta2 : 4; + uint64_t dpll_char_delta1 : 4; + uint64_t override_pcbs_dpll_synchronizer : 1; + uint64_t pre_vret_pstate : 8; + uint64_t dpll_lock_timer_replacement_value : 9; + uint64_t dco_decr : 1; + uint64_t dco_incr : 1; + uint64_t dco_override : 1; + uint64_t ff_bypassxpi : 1; + uint64_t cpm_filter_enable : 1; + uint64_t ff_use_cpmxpi : 1; + uint64_t lf_use_cpmxpi : 1; + uint64_t lf_slewratexpi : 8; +#endif // _BIG_ENDIAN + } fields; +} pcbs_dpll_cpm_parm_reg_t; + + + +typedef union pcbs_power_management_status_reg { + + 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 + int64_t global_pstate_actual : 8; + int64_t local_pstate_actual : 8; + int64_t pv_min : 8; + int64_t pvf_max : 8; + uint64_t spr_em_disabled : 1; + uint64_t psafe_mode_active : 1; + uint64_t ivrm_safe_mode_active : 1; + uint64_t ivrm_enable : 1; + uint64_t all_fsms_in_safe_state : 1; + uint64_t pmsr_spares : 4; + uint64_t _reserved0 : 23; +#else + uint64_t _reserved0 : 23; + uint64_t pmsr_spares : 4; + uint64_t all_fsms_in_safe_state : 1; + uint64_t ivrm_enable : 1; + uint64_t ivrm_safe_mode_active : 1; + uint64_t psafe_mode_active : 1; + uint64_t spr_em_disabled : 1; + int64_t pvf_max : 8; + int64_t pv_min : 8; + int64_t local_pstate_actual : 8; + int64_t global_pstate_actual : 8; +#endif // _BIG_ENDIAN + } fields; +} pcbs_power_management_status_reg_t; + + + +typedef union pcbs_ivrm_control_status_reg { + + 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 ivrm_fsm_enable : 1; + uint64_t use_ivrm_for_vret : 1; + uint64_t binsearch_cal_ena : 1; + uint64_t pvref_en : 1; + uint64_t ivrm_core_vdd_bypass_b : 1; + uint64_t ivrm_core_vdd_poweron : 1; + uint64_t ivrm_core_vcs_bypass_b : 1; + uint64_t ivrm_core_vcs_poweron : 1; + uint64_t ivrm_eco_vdd_bypass_b : 1; + uint64_t ivrm_eco_vdd_poweron : 1; + uint64_t ivrm_eco_vcs_bypass_b : 1; + uint64_t ivrm_eco_vcs_poweron : 1; + uint64_t ivrm_vret_vdd : 7; + uint64_t ivrm_vret_vcs : 7; + uint64_t ivrm_vret_core_vdd_pfet_strength : 5; + uint64_t ivrm_vret_core_vcs_pfet_strength : 5; + uint64_t ivrm_vret_eco_vdd_pfet_strength : 5; + uint64_t ivrm_vret_eco_vcs_pfet_strength : 5; + uint64_t pvref_fail : 1; + uint64_t ivrm_pref_error_gross : 1; + uint64_t ivrm_pref_error_fine : 1; + uint64_t ivrm_core_vdd_range_hi : 1; + uint64_t ivrm_core_vdd_range_lo : 1; + uint64_t ivrm_eco_vdd_range_hi : 1; + uint64_t ivrm_eco_vdd_range_lo : 1; + uint64_t ivrm_core_vcs_range_hi : 1; + uint64_t ivrm_core_vcs_range_lo : 1; + uint64_t ivrm_eco_vcs_range_hi : 1; + uint64_t ivrm_eco_vcs_range_lo : 1; + uint64_t binsearch_cal_done : 1; + uint64_t ivrm_core_vdd_pfet_low_vout : 1; + uint64_t ivrm_core_vcs_pfet_low_vout : 1; + uint64_t ivrm_eco_vdd_pfet_low_vout : 1; + uint64_t ivrm_eco_vcs_pfet_low_vout : 1; + uint64_t ivrm_power_down_disable : 1; + uint64_t _reserved0 : 1; +#else + uint64_t _reserved0 : 1; + uint64_t ivrm_power_down_disable : 1; + uint64_t ivrm_eco_vcs_pfet_low_vout : 1; + uint64_t ivrm_eco_vdd_pfet_low_vout : 1; + uint64_t ivrm_core_vcs_pfet_low_vout : 1; + uint64_t ivrm_core_vdd_pfet_low_vout : 1; + uint64_t binsearch_cal_done : 1; + uint64_t ivrm_eco_vcs_range_lo : 1; + uint64_t ivrm_eco_vcs_range_hi : 1; + uint64_t ivrm_core_vcs_range_lo : 1; + uint64_t ivrm_core_vcs_range_hi : 1; + uint64_t ivrm_eco_vdd_range_lo : 1; + uint64_t ivrm_eco_vdd_range_hi : 1; + uint64_t ivrm_core_vdd_range_lo : 1; + uint64_t ivrm_core_vdd_range_hi : 1; + uint64_t ivrm_pref_error_fine : 1; + uint64_t ivrm_pref_error_gross : 1; + uint64_t pvref_fail : 1; + uint64_t ivrm_vret_eco_vcs_pfet_strength : 5; + uint64_t ivrm_vret_eco_vdd_pfet_strength : 5; + uint64_t ivrm_vret_core_vcs_pfet_strength : 5; + uint64_t ivrm_vret_core_vdd_pfet_strength : 5; + uint64_t ivrm_vret_vcs : 7; + uint64_t ivrm_vret_vdd : 7; + uint64_t ivrm_eco_vcs_poweron : 1; + uint64_t ivrm_eco_vcs_bypass_b : 1; + uint64_t ivrm_eco_vdd_poweron : 1; + uint64_t ivrm_eco_vdd_bypass_b : 1; + uint64_t ivrm_core_vcs_poweron : 1; + uint64_t ivrm_core_vcs_bypass_b : 1; + uint64_t ivrm_core_vdd_poweron : 1; + uint64_t ivrm_core_vdd_bypass_b : 1; + uint64_t pvref_en : 1; + uint64_t binsearch_cal_ena : 1; + uint64_t use_ivrm_for_vret : 1; + uint64_t ivrm_fsm_enable : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_ivrm_control_status_reg_t; + + + +typedef union pcbs_ivrm_value_setting_reg { + + 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 ivrm_core_vdd_ivid : 8; + uint64_t ivrm_core_vcs_ivid : 8; + uint64_t ivrm_eco_vdd_ivid : 8; + uint64_t ivrm_eco_vcs_ivid : 8; + uint64_t ivrm_core_vdd_pfet_strength : 5; + uint64_t ivrm_core_vcs_pfet_strength : 5; + uint64_t ivrm_eco_vdd_pfet_strength : 5; + uint64_t ivrm_eco_vcs_pfet_strength : 5; + uint64_t ivrm_vdd_core_pfetstr_valid : 1; + uint64_t ivrm_vcs_core_pfetstr_valid : 1; + uint64_t ivrm_vdd_eco_pfetstr_valid : 1; + uint64_t ivrm_vcs_eco_pfetstr_valid : 1; + uint64_t core_vdd_vpump_en : 1; + uint64_t core_vcs_vpump_en : 1; + uint64_t eco_vdd_vpump_en : 1; + uint64_t eco_vcs_vpump_en : 1; + uint64_t _reserved0 : 4; +#else + uint64_t _reserved0 : 4; + uint64_t eco_vcs_vpump_en : 1; + uint64_t eco_vdd_vpump_en : 1; + uint64_t core_vcs_vpump_en : 1; + uint64_t core_vdd_vpump_en : 1; + uint64_t ivrm_vcs_eco_pfetstr_valid : 1; + uint64_t ivrm_vdd_eco_pfetstr_valid : 1; + uint64_t ivrm_vcs_core_pfetstr_valid : 1; + uint64_t ivrm_vdd_core_pfetstr_valid : 1; + uint64_t ivrm_eco_vcs_pfet_strength : 5; + uint64_t ivrm_eco_vdd_pfet_strength : 5; + uint64_t ivrm_core_vcs_pfet_strength : 5; + uint64_t ivrm_core_vdd_pfet_strength : 5; + uint64_t ivrm_eco_vcs_ivid : 8; + uint64_t ivrm_eco_vdd_ivid : 8; + uint64_t ivrm_core_vcs_ivid : 8; + uint64_t ivrm_core_vdd_ivid : 8; +#endif // _BIG_ENDIAN + } fields; +} pcbs_ivrm_value_setting_reg_t; + + + +typedef union pcbs_pcbspm_mode_reg { + + 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 enable_pstate_mode : 1; + uint64_t global_pstate_change_for_idle_state_enabled : 1; + uint64_t enable_global_pstate_req : 1; + uint64_t enable_winkle_with_cpm_mode : 1; + uint64_t enable_clipping_of_global_pstate_req : 1; + uint64_t chksw_hw214553 : 1; + uint64_t enable_pmc_pmax_sync_notification : 1; + uint64_t dpll_lock_replacement_timer_mode_en : 1; + uint64_t dpll_freqout_mode_en : 1; + uint64_t dpll_flock_mode_en : 1; + uint64_t enable_sense_delay_characterization : 1; + uint64_t sense_delay_timer_val : 7; + uint64_t cpm_fmin_clip_error_sel : 2; + uint64_t dbg_trace_sel : 4; + uint64_t trace_data_sel : 2; + uint64_t tp_cplt_ivrm_vpp_tune : 4; + uint64_t _reserved0 : 34; +#else + uint64_t _reserved0 : 34; + uint64_t tp_cplt_ivrm_vpp_tune : 4; + uint64_t trace_data_sel : 2; + uint64_t dbg_trace_sel : 4; + uint64_t cpm_fmin_clip_error_sel : 2; + uint64_t sense_delay_timer_val : 7; + uint64_t enable_sense_delay_characterization : 1; + uint64_t dpll_flock_mode_en : 1; + uint64_t dpll_freqout_mode_en : 1; + uint64_t dpll_lock_replacement_timer_mode_en : 1; + uint64_t enable_pmc_pmax_sync_notification : 1; + uint64_t chksw_hw214553 : 1; + uint64_t enable_clipping_of_global_pstate_req : 1; + uint64_t enable_winkle_with_cpm_mode : 1; + uint64_t enable_global_pstate_req : 1; + uint64_t global_pstate_change_for_idle_state_enabled : 1; + uint64_t enable_pstate_mode : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pcbspm_mode_reg_t; + +#endif // __ASSEMBLER__ +#define PCBS_PCBSPM_MODE_REG_ENABLE_PSTATE_MODE SIXTYFOUR_BIT_CONSTANT(0x8000000000000000) +#define PCBS_PCBSPM_MODE_REG_GLOBAL_PSTATE_CHANGE_FOR_IDLE_STATE_ENABLED SIXTYFOUR_BIT_CONSTANT(0x4000000000000000) +#define PCBS_PCBSPM_MODE_REG_ENABLE_GLOBAL_PSTATE_REQ SIXTYFOUR_BIT_CONSTANT(0x2000000000000000) +#define PCBS_PCBSPM_MODE_REG_ENABLE_WINKLE_WITH_CPM_MODE SIXTYFOUR_BIT_CONSTANT(0x1000000000000000) +#define PCBS_PCBSPM_MODE_REG_ENABLE_CLIPPING_OF_GLOBAL_PSTATE_REQ SIXTYFOUR_BIT_CONSTANT(0x0800000000000000) +#define PCBS_PCBSPM_MODE_REG_CHKSW_HW214553 SIXTYFOUR_BIT_CONSTANT(0x0400000000000000) +#define PCBS_PCBSPM_MODE_REG_ENABLE_PMC_PMAX_SYNC_NOTIFICATION SIXTYFOUR_BIT_CONSTANT(0x0200000000000000) +#define PCBS_PCBSPM_MODE_REG_DPLL_LOCK_REPLACEMENT_TIMER_MODE_EN SIXTYFOUR_BIT_CONSTANT(0x0100000000000000) +#define PCBS_PCBSPM_MODE_REG_DPLL_FREQOUT_MODE_EN SIXTYFOUR_BIT_CONSTANT(0x0080000000000000) +#define PCBS_PCBSPM_MODE_REG_DPLL_FLOCK_MODE_EN SIXTYFOUR_BIT_CONSTANT(0x0040000000000000) +#define PCBS_PCBSPM_MODE_REG_ENABLE_SENSE_DELAY_CHARACTERIZATION SIXTYFOUR_BIT_CONSTANT(0x0020000000000000) +#define PCBS_PCBSPM_MODE_REG_SENSE_DELAY_TIMER_VAL_MASK SIXTYFOUR_BIT_CONSTANT(0x001fc00000000000) +#define PCBS_PCBSPM_MODE_REG_CPM_FMIN_CLIP_ERROR_SEL_MASK SIXTYFOUR_BIT_CONSTANT(0x0000300000000000) +#define PCBS_PCBSPM_MODE_REG_DBG_TRACE_SEL_MASK SIXTYFOUR_BIT_CONSTANT(0x00000f0000000000) +#define PCBS_PCBSPM_MODE_REG_TRACE_DATA_SEL_MASK SIXTYFOUR_BIT_CONSTANT(0x000000c000000000) +#define PCBS_PCBSPM_MODE_REG_TP_CPLT_IVRM_VPP_TUNE_MASK SIXTYFOUR_BIT_CONSTANT(0x0000003c00000000) +#ifndef __ASSEMBLER__ + + +typedef union pcbs_ivrm_pfetstr_sense_reg { + + 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 ivrm_core_vdd_pfetstr_sns : 5; + uint64_t ivrm_core_vcs_pfetstr_sns : 5; + uint64_t ivrm_eco_vdd_pfetstr_sns : 5; + uint64_t ivrm_eco_vcs_pfetstr_sns : 5; + uint64_t ivrm_vdd_core_pfetstr_valid_sns : 1; + uint64_t ivrm_vcs_core_pfetstr_valid_sns : 1; + uint64_t ivrm_vdd_eco_pfetstr_valid_sns : 1; + uint64_t ivrm_vcs_eco_pfetstr_valid_sns : 1; + uint64_t core_vdd_bypass_b_sense : 1; + uint64_t core_vcs_bypass_b_sense : 1; + uint64_t eco_vdd_bypass_b_sense : 1; + uint64_t eco_vcs_bypass_b_sense : 1; + uint64_t core_vdd_poweron_sense : 1; + uint64_t core_vcs_poweron_sense : 1; + uint64_t eco_vdd_poweron_sense : 1; + uint64_t eco_vcs_poweron_sense : 1; + uint64_t core_vdd_vpump_en_sense : 1; + uint64_t core_vcs_vpump_en_sense : 1; + uint64_t eco_vdd_vpump_en_sense : 1; + uint64_t eco_vcs_vpump_en_sense : 1; + uint64_t core_vdd_pfet_low_vout_sns : 1; + uint64_t core_vcs_pfet_low_vout_sns : 1; + uint64_t eco_vdd_pfet_low_vout_sns : 1; + uint64_t eco_vcs_pfet_low_vout_sns : 1; + uint64_t _reserved0 : 24; +#else + uint64_t _reserved0 : 24; + uint64_t eco_vcs_pfet_low_vout_sns : 1; + uint64_t eco_vdd_pfet_low_vout_sns : 1; + uint64_t core_vcs_pfet_low_vout_sns : 1; + uint64_t core_vdd_pfet_low_vout_sns : 1; + uint64_t eco_vcs_vpump_en_sense : 1; + uint64_t eco_vdd_vpump_en_sense : 1; + uint64_t core_vcs_vpump_en_sense : 1; + uint64_t core_vdd_vpump_en_sense : 1; + uint64_t eco_vcs_poweron_sense : 1; + uint64_t eco_vdd_poweron_sense : 1; + uint64_t core_vcs_poweron_sense : 1; + uint64_t core_vdd_poweron_sense : 1; + uint64_t eco_vcs_bypass_b_sense : 1; + uint64_t eco_vdd_bypass_b_sense : 1; + uint64_t core_vcs_bypass_b_sense : 1; + uint64_t core_vdd_bypass_b_sense : 1; + uint64_t ivrm_vcs_eco_pfetstr_valid_sns : 1; + uint64_t ivrm_vdd_eco_pfetstr_valid_sns : 1; + uint64_t ivrm_vcs_core_pfetstr_valid_sns : 1; + uint64_t ivrm_vdd_core_pfetstr_valid_sns : 1; + uint64_t ivrm_eco_vcs_pfetstr_sns : 5; + uint64_t ivrm_eco_vdd_pfetstr_sns : 5; + uint64_t ivrm_core_vcs_pfetstr_sns : 5; + uint64_t ivrm_core_vdd_pfetstr_sns : 5; +#endif // _BIG_ENDIAN + } fields; +} pcbs_ivrm_pfetstr_sense_reg_t; + + + +typedef union pcbs_power_management_idle_control_reg { + + 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 + int64_t nap_pstate_req : 8; + uint64_t nap_pstate_en : 1; + uint64_t nap_global_en : 1; + uint64_t nap_latency : 2; + uint64_t reserved_ppmicr_0 : 4; + int64_t sleep_pstate_req : 8; + uint64_t sleep_pstate_en : 1; + uint64_t sleep_global_en : 1; + uint64_t sleep_latency : 2; + uint64_t reserved_ppmicr_1 : 4; + int64_t winkle_pstate_req : 8; + uint64_t winkle_pstate_en : 1; + uint64_t winkle_global_en : 1; + uint64_t winkle_latency : 2; + uint64_t reserved_ppmicr_2 : 4; + uint64_t _reserved0 : 16; +#else + uint64_t _reserved0 : 16; + uint64_t reserved_ppmicr_2 : 4; + uint64_t winkle_latency : 2; + uint64_t winkle_global_en : 1; + uint64_t winkle_pstate_en : 1; + int64_t winkle_pstate_req : 8; + uint64_t reserved_ppmicr_1 : 4; + uint64_t sleep_latency : 2; + uint64_t sleep_global_en : 1; + uint64_t sleep_pstate_en : 1; + int64_t sleep_pstate_req : 8; + uint64_t reserved_ppmicr_0 : 4; + uint64_t nap_latency : 2; + uint64_t nap_global_en : 1; + uint64_t nap_pstate_en : 1; + int64_t nap_pstate_req : 8; +#endif // _BIG_ENDIAN + } fields; +} pcbs_power_management_idle_control_reg_t; + + + +typedef union pcbs_power_management_control_reg { + + 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 + int64_t global_pstate_req : 8; + int64_t local_pstate_req : 8; + uint64_t auto_override0_pstate_limit_en : 1; + uint64_t auto_override1_pstate_limit_en : 1; + uint64_t reserved_ppmcr : 6; + int64_t auto_override_pstate0 : 8; + int64_t auto_override_pstate1 : 8; + uint64_t _reserved0 : 24; +#else + uint64_t _reserved0 : 24; + int64_t auto_override_pstate1 : 8; + int64_t auto_override_pstate0 : 8; + uint64_t reserved_ppmcr : 6; + uint64_t auto_override1_pstate_limit_en : 1; + uint64_t auto_override0_pstate_limit_en : 1; + int64_t local_pstate_req : 8; + int64_t global_pstate_req : 8; +#endif // _BIG_ENDIAN + } fields; +} pcbs_power_management_control_reg_t; + + + +typedef union pcbs_pmc_vf_ctrl_reg { + + 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 + int64_t pglobal_actual : 8; + uint64_t maxregvcs : 8; + uint64_t maxregvdd : 8; + uint64_t evidvcs_eff : 8; + uint64_t evidvdd_eff : 8; + uint64_t _reserved0 : 24; +#else + uint64_t _reserved0 : 24; + uint64_t evidvdd_eff : 8; + uint64_t evidvcs_eff : 8; + uint64_t maxregvdd : 8; + uint64_t maxregvcs : 8; + int64_t pglobal_actual : 8; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pmc_vf_ctrl_reg_t; + + + +typedef union pcbs_undervolting_reg { + + 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 + int64_t puv_min : 8; + int64_t puv_max : 8; + uint64_t kuv : 6; + uint64_t _reserved0 : 42; +#else + uint64_t _reserved0 : 42; + uint64_t kuv : 6; + int64_t puv_max : 8; + int64_t puv_min : 8; +#endif // _BIG_ENDIAN + } fields; +} pcbs_undervolting_reg_t; + + + +typedef union pcbs_pstate_index_bound_reg { + + 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 lpsi_min : 8; + uint64_t lpsi_entries_minus_1 : 7; + uint64_t _reserved0 : 49; +#else + uint64_t _reserved0 : 49; + uint64_t lpsi_entries_minus_1 : 7; + uint64_t lpsi_min : 8; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pstate_index_bound_reg_t; + + + +typedef union pcbs_power_management_bounds_reg { + + 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 + int64_t pmin_clip : 8; + int64_t pmax_clip : 8; + uint64_t _reserved0 : 48; +#else + uint64_t _reserved0 : 48; + int64_t pmax_clip : 8; + int64_t pmin_clip : 8; +#endif // _BIG_ENDIAN + } fields; +} pcbs_power_management_bounds_reg_t; + + + +typedef union pcbs_pstate_table_ctrl_reg { + + 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 pstate_table_address : 7; + uint64_t _reserved0 : 57; +#else + uint64_t _reserved0 : 57; + uint64_t pstate_table_address : 7; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pstate_table_ctrl_reg_t; + + + +typedef union pcbs_pstate_table_reg { + + 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 pstate_data : 64; +#else + uint64_t pstate_data : 64; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pstate_table_reg_t; + + + +typedef union pcbs_pstate_step_target_reg { + + 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 + int64_t local_pstate_eff_req : 8; + int64_t local_pstate_target : 8; + int64_t local_core_pstate_step_target : 8; + int64_t local_eco_pstate_step_target : 8; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + int64_t local_eco_pstate_step_target : 8; + int64_t local_core_pstate_step_target : 8; + int64_t local_pstate_target : 8; + int64_t local_pstate_eff_req : 8; +#endif // _BIG_ENDIAN + } fields; +} pcbs_pstate_step_target_reg_t; + + + +typedef union pcbs_dpll_status_reg { + + 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 dpll_ff_freqout : 15; + uint64_t dpll_frequ_change : 1; + uint64_t dpll_status_spare_bit1 : 1; + uint64_t pmax_sync_pending : 1; + uint64_t ga_ack_pending : 1; + int64_t capped_global_pstate_req : 8; + uint64_t dpll_fmax_and_cpmbit2 : 1; + uint64_t dpll_fmax_and_cpmbit3 : 1; + uint64_t dpll_fmax_and_cpmbit4 : 1; + uint64_t dpll_fmin_and_not_cpmbit2 : 1; + uint64_t dpll_fmin_and_not_cpmbit1 : 1; + uint64_t dpll_fmin_and_not_cpmbit0 : 1; + uint64_t dpll_faster_than_fmax_plus_delta1 : 1; + uint64_t dpll_slower_than_fmin_minus_delta2 : 1; + uint64_t dpll_max_freqout_after_last_read : 14; + uint64_t dpll_min_freqout_after_last_read : 14; + uint64_t _reserved0 : 1; +#else + uint64_t _reserved0 : 1; + uint64_t dpll_min_freqout_after_last_read : 14; + uint64_t dpll_max_freqout_after_last_read : 14; + uint64_t dpll_slower_than_fmin_minus_delta2 : 1; + uint64_t dpll_faster_than_fmax_plus_delta1 : 1; + uint64_t dpll_fmin_and_not_cpmbit0 : 1; + uint64_t dpll_fmin_and_not_cpmbit1 : 1; + uint64_t dpll_fmin_and_not_cpmbit2 : 1; + uint64_t dpll_fmax_and_cpmbit4 : 1; + uint64_t dpll_fmax_and_cpmbit3 : 1; + uint64_t dpll_fmax_and_cpmbit2 : 1; + int64_t capped_global_pstate_req : 8; + uint64_t ga_ack_pending : 1; + uint64_t pmax_sync_pending : 1; + uint64_t dpll_status_spare_bit1 : 1; + uint64_t dpll_frequ_change : 1; + uint64_t dpll_ff_freqout : 15; +#endif // _BIG_ENDIAN + } fields; +} pcbs_dpll_status_reg_t; + + + +typedef union pcbs_ivrm_vid_control_reg0 { + + 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 ivrm_req_pstate_stepdelay_rising : 8; + uint64_t ivrm_req_pstate_stepdelay_lowering : 8; + uint64_t _reserved0 : 48; +#else + uint64_t _reserved0 : 48; + uint64_t ivrm_req_pstate_stepdelay_lowering : 8; + uint64_t ivrm_req_pstate_stepdelay_rising : 8; +#endif // _BIG_ENDIAN + } fields; +} pcbs_ivrm_vid_control_reg0_t; + + + +typedef union pcbs_ivrm_vid_control_reg1 { + + 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 ivrm_stabilize_delay_run : 8; + uint64_t ivrm_stabilize_delay_idle : 8; + uint64_t ivrm_pfstr_prop_delay : 8; + uint64_t ivrm_pfstrvalid_prop_delay : 8; + uint64_t ivrm_vpump_poweron_time : 8; + uint64_t ivrm_bypass_delay : 8; + uint64_t pfet_vpump_enable_delay : 8; + uint64_t ivrm_vid_vout_threshold : 7; + uint64_t _reserved0 : 1; +#else + uint64_t _reserved0 : 1; + uint64_t ivrm_vid_vout_threshold : 7; + uint64_t pfet_vpump_enable_delay : 8; + uint64_t ivrm_bypass_delay : 8; + uint64_t ivrm_vpump_poweron_time : 8; + uint64_t ivrm_pfstrvalid_prop_delay : 8; + uint64_t ivrm_pfstr_prop_delay : 8; + uint64_t ivrm_stabilize_delay_idle : 8; + uint64_t ivrm_stabilize_delay_run : 8; +#endif // _BIG_ENDIAN + } fields; +} pcbs_ivrm_vid_control_reg1_t; + + + +typedef union pcbs_occ_heartbeat_reg { + + 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 occ_heartbeat_time : 8; + uint64_t occ_heartbeat_enable : 1; + uint64_t occ_heartbeat_reg_addr_offset : 8; + int64_t psafe : 8; + uint64_t _reserved0 : 39; +#else + uint64_t _reserved0 : 39; + int64_t psafe : 8; + uint64_t occ_heartbeat_reg_addr_offset : 8; + uint64_t occ_heartbeat_enable : 1; + uint64_t occ_heartbeat_time : 8; +#endif // _BIG_ENDIAN + } fields; +} pcbs_occ_heartbeat_reg_t; + + + +typedef union pcbs_resonant_clock_control_reg0 { + + 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 resclk_dis : 1; + uint64_t resclk_control_mode : 1; + uint64_t resclk_sync_pw : 3; + uint64_t res_sync_delay_cnt : 7; + uint64_t res_csb_str_instr_lo : 15; + uint64_t res_csb_str_instr_hi : 15; + uint64_t _reserved0 : 22; +#else + uint64_t _reserved0 : 22; + uint64_t res_csb_str_instr_hi : 15; + uint64_t res_csb_str_instr_lo : 15; + uint64_t res_sync_delay_cnt : 7; + uint64_t resclk_sync_pw : 3; + uint64_t resclk_control_mode : 1; + uint64_t resclk_dis : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_resonant_clock_control_reg0_t; + + + +typedef union pcbs_resonant_clock_control_reg1 { + + 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 + int64_t full_csb_ps : 8; + int64_t res_low_lower_ps : 8; + int64_t res_low_upper_ps : 8; + int64_t res_high_lower_ps : 8; + int64_t res_high_upper_ps : 8; + uint64_t nonres_csb_value_ti : 4; + uint64_t full_csb_value_ti : 4; + uint64_t resclk_value : 9; + uint64_t resclk_core_sync_value : 1; + uint64_t csb_eco_sync_value : 1; + uint64_t _reserved0 : 5; +#else + uint64_t _reserved0 : 5; + uint64_t csb_eco_sync_value : 1; + uint64_t resclk_core_sync_value : 1; + uint64_t resclk_value : 9; + uint64_t full_csb_value_ti : 4; + uint64_t nonres_csb_value_ti : 4; + int64_t res_high_upper_ps : 8; + int64_t res_high_lower_ps : 8; + int64_t res_low_upper_ps : 8; + int64_t res_low_lower_ps : 8; + int64_t full_csb_ps : 8; +#endif // _BIG_ENDIAN + } fields; +} pcbs_resonant_clock_control_reg1_t; + + + +typedef union pcbs_resonant_clock_status_reg { + + 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 resclk_state : 1; + uint64_t res_hi_induct_en : 1; + uint64_t resclk_inprogress : 1; + uint64_t resclk_full_csb : 1; + uint64_t _reserved0 : 60; +#else + uint64_t _reserved0 : 60; + uint64_t resclk_full_csb : 1; + uint64_t resclk_inprogress : 1; + uint64_t res_hi_induct_en : 1; + uint64_t resclk_state : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_resonant_clock_status_reg_t; + + + +typedef union pcbs_local_pstate_frequency_target_control_reg { + + 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 delay_time : 3; + uint64_t record_transitions : 1; + uint64_t multiplier : 15; + uint64_t enable_lpft_function : 1; + uint64_t _reserved0 : 44; +#else + uint64_t _reserved0 : 44; + uint64_t enable_lpft_function : 1; + uint64_t multiplier : 15; + uint64_t record_transitions : 1; + uint64_t delay_time : 3; +#endif // _BIG_ENDIAN + } fields; +} pcbs_local_pstate_frequency_target_control_reg_t; + + + +typedef union pcbs_local_pstate_frequency_target_status_reg { + + 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 valid : 1; + uint64_t cpm_dpll : 1; + uint64_t ivrm : 1; + uint64_t transition : 1; + uint64_t stable : 1; + uint64_t delta : 24; + uint64_t cumulative : 24; + uint64_t pstate : 8; + uint64_t _reserved0 : 3; +#else + uint64_t _reserved0 : 3; + uint64_t pstate : 8; + uint64_t cumulative : 24; + uint64_t delta : 24; + uint64_t stable : 1; + uint64_t transition : 1; + uint64_t ivrm : 1; + uint64_t cpm_dpll : 1; + uint64_t valid : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_local_pstate_frequency_target_status_reg_t; + + + +typedef union pcbs_fsm_monitor1_reg { + + 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 babystep_main_fsm : 7; + uint64_t babystep_slave_fsm : 5; + uint64_t core_railstepper_main_fsm : 5; + uint64_t eco_railstepper_main_fsm : 5; + uint64_t core_railstepper_sub_fsm : 4; + uint64_t eco_railstepper_sub_fsm : 4; + uint64_t core_railstepper_byp_fsm : 5; + uint64_t eco_railstepper_byp_fsm : 5; + uint64_t ivrm_core_vdd_sequencer_fsm : 6; + uint64_t ivrm_core_vcs_sequencer_fsm : 6; + uint64_t ivrm_eco_vdd_sequencer_fsm : 6; + uint64_t ivrm_eco_vcs_sequencer_fsm : 6; +#else + uint64_t ivrm_eco_vcs_sequencer_fsm : 6; + uint64_t ivrm_eco_vdd_sequencer_fsm : 6; + uint64_t ivrm_core_vcs_sequencer_fsm : 6; + uint64_t ivrm_core_vdd_sequencer_fsm : 6; + uint64_t eco_railstepper_byp_fsm : 5; + uint64_t core_railstepper_byp_fsm : 5; + uint64_t eco_railstepper_sub_fsm : 4; + uint64_t core_railstepper_sub_fsm : 4; + uint64_t eco_railstepper_main_fsm : 5; + uint64_t core_railstepper_main_fsm : 5; + uint64_t babystep_slave_fsm : 5; + uint64_t babystep_main_fsm : 7; +#endif // _BIG_ENDIAN + } fields; +} pcbs_fsm_monitor1_reg_t; + + + +typedef union pcbs_fsm_monitor2_reg { + + 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 resclk_band_fsm : 7; + uint64_t resclk_lowres_fsm : 4; + uint64_t resclk_highres_fsm : 4; + uint64_t resclk_fullcsb_fsm : 4; + uint64_t resclk_update_fsm : 4; + uint64_t idle_transition_fsm : 7; + uint64_t peco_step_target_uv : 8; + uint64_t pcore_step_target_uv : 8; + uint64_t _reserved0 : 18; +#else + uint64_t _reserved0 : 18; + uint64_t pcore_step_target_uv : 8; + uint64_t peco_step_target_uv : 8; + uint64_t idle_transition_fsm : 7; + uint64_t resclk_update_fsm : 4; + uint64_t resclk_fullcsb_fsm : 4; + uint64_t resclk_highres_fsm : 4; + uint64_t resclk_lowres_fsm : 4; + uint64_t resclk_band_fsm : 7; +#endif // _BIG_ENDIAN + } fields; +} pcbs_fsm_monitor2_reg_t; + + + +typedef union pcbs_chksw_unassisted_interrupts { + + 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 : 1; + uint64_t _reserved0 : 63; +#else + uint64_t _reserved0 : 63; + uint64_t value : 1; +#endif // _BIG_ENDIAN + } fields; +} pcbs_chksw_unassisted_interrupts_t; + + +#endif // __ASSEMBLER__ +#endif // __PCBS_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/pcbs_register_addresses.h b/src/ssx/pgp/registers/pcbs_register_addresses.h new file mode 100755 index 0000000..8c465d1 --- /dev/null +++ b/src/ssx/pgp/registers/pcbs_register_addresses.h @@ -0,0 +1,74 @@ +#ifndef __PCBS_REGISTER_ADDRESSES_H__ +#define __PCBS_REGISTER_ADDRESSES_H__ + +// $Id: pcbs_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:24 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pcbs_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pcbs_register_addresses.h +/// \brief Symbolic addresses for the PCBS unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define PCBS_PIB_BASE 0x100f0100 +#define PCBS_PMGP0_REG 0x100f0100 +#define PCBS_PMGP0_REG_AND 0x100f0101 +#define PCBS_PMGP0_REG_OR 0x100f0102 +#define PCBS_PMGP1_REG 0x100f0103 +#define PCBS_PMGP1_REG_AND 0x100f0104 +#define PCBS_PMGP1_REG_OR 0x100f0105 +#define PCBS_PFVDDCNTLSTAT_REG 0x100f0106 +#define PCBS_PFVCSCNTLSTAT_REG 0x100f010e +#define PCBS_PFSENSE_REG 0x100f0107 +#define PCBS_PMERRSUM_REG 0x100f0108 +#define PCBS_PMERR_REG 0x100f0109 +#define PCBS_PMERRMASK_REG 0x100f010a +#define PCBS_PMSPCWKUPFSP_REG 0x100f010b +#define PCBS_PMSPCWKUPOCC_REG 0x100f010c +#define PCBS_PMSPCWKUPPHYP_REG 0x100f010d +#define PCBS_PMSTATEHISTPHYP_REG 0x100f0110 +#define PCBS_PMSTATEHISTFSP_REG 0x100f0111 +#define PCBS_PMSTATEHISTOCC_REG 0x100f0112 +#define PCBS_PMSTATEHISTPERF_REG 0x100f0113 +#define PCBS_IDLEFSMGOTOCMD_REG 0x100f0114 +#define PCBS_COREPFPUDLY_REG 0x100f012c +#define PCBS_COREPFPDDLY_REG 0x100f012d +#define PCBS_COREPFVRET_REG 0x100f0130 +#define PCBS_ECOPFPUDLY_REG 0x100f014c +#define PCBS_ECOPFPDDLY_REG 0x100f014d +#define PCBS_ECOPFVRET_REG 0x100f0150 +#define PCBS_FREQ_CTRL_REG 0x100f0151 +#define PCBS_DPLL_CPM_PARM_REG 0x100f0152 +#define PCBS_POWER_MANAGEMENT_STATUS_REG 0x100f0153 +#define PCBS_IVRM_CONTROL_STATUS_REG 0x100f0154 +#define PCBS_IVRM_VALUE_SETTING_REG 0x100f0155 +#define PCBS_PCBSPM_MODE_REG 0x100f0156 +#define PCBS_IVRM_PFETSTR_SENSE_REG 0x100f0157 +#define PCBS_POWER_MANAGEMENT_IDLE_CONTROL_REG 0x100f0158 +#define PCBS_POWER_MANAGEMENT_CONTROL_REG 0x100f0159 +#define PCBS_PMC_VF_CTRL_REG 0x100f015a +#define PCBS_UNDERVOLTING_REG 0x100f015b +#define PCBS_PSTATE_INDEX_BOUND_REG 0x100f015c +#define PCBS_POWER_MANAGEMENT_BOUNDS_REG 0x100f015d +#define PCBS_PSTATE_TABLE_CTRL_REG 0x100f015e +#define PCBS_PSTATE_TABLE_REG 0x100f015f +#define PCBS_PSTATE_STEP_TARGET_REG 0x100f0160 +#define PCBS_DPLL_STATUS_REG 0x100f0161 +#define PCBS_IVRM_VID_CONTROL_REG0 0x100f0162 +#define PCBS_IVRM_VID_CONTROL_REG1 0x100f0163 +#define PCBS_OCC_HEARTBEAT_REG 0x100f0164 +#define PCBS_RESONANT_CLOCK_CONTROL_REG0 0x100f0165 +#define PCBS_RESONANT_CLOCK_CONTROL_REG1 0x100f0166 +#define PCBS_RESONANT_CLOCK_STATUS_REG 0x100f0167 +#define PCBS_LOCAL_PSTATE_FREQUENCY_TARGET_CONTROL_REG 0x100f0168 +#define PCBS_LOCAL_PSTATE_FREQUENCY_TARGET_STATUS_REG 0x100f0169 +#define PCBS_FSM_MONITOR1_REG 0x100f0170 +#define PCBS_FSM_MONITOR2_REG 0x100f0171 + +#endif // __PCBS_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/pibmem_firmware_registers.h b/src/ssx/pgp/registers/pibmem_firmware_registers.h new file mode 100644 index 0000000..3b36fc1 --- /dev/null +++ b/src/ssx/pgp/registers/pibmem_firmware_registers.h @@ -0,0 +1,264 @@ +#ifndef __PIBMEM_FIRMWARE_REGISTERS_H__ +#define __PIBMEM_FIRMWARE_REGISTERS_H__ + +// $Id: pibmem_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pibmem_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pibmem_firmware_registers.h +/// \brief C register structs for the PIBMEM unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union pibmem_data0 { + + 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; +} pibmem_data0_t; + + + +typedef union pibmem_control { + + 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 auto_pre_increment : 1; + uint64_t auto_post_decrement : 1; + uint64_t _reserved0 : 62; +#else + uint64_t _reserved0 : 62; + uint64_t auto_post_decrement : 1; + uint64_t auto_pre_increment : 1; +#endif // _BIG_ENDIAN + } fields; +} pibmem_control_t; + + + +typedef union pibmem_address { + + 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 reserved0 : 48; + uint64_t address : 16; +#else + uint64_t address : 16; + uint64_t reserved0 : 48; +#endif // _BIG_ENDIAN + } fields; +} pibmem_address_t; + + + +typedef union pibmem_data { + + 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; +} pibmem_data_t; + + + +typedef union pibmem_data_inc { + + 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; +} pibmem_data_inc_t; + + + +typedef union pibmem_data_dec { + + 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; +} pibmem_data_dec_t; + + + +typedef union pibmem_status { + + 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 addr_invalid : 1; + uint64_t write_invalid : 1; + uint64_t read_invalid : 1; + uint64_t ecc_uncorrected_error : 1; + uint64_t ecc_corrected_error : 1; + uint64_t bad_array_address : 1; + uint64_t reserved6 : 5; + uint64_t fsm_present_state : 7; + uint64_t _reserved0 : 46; +#else + uint64_t _reserved0 : 46; + uint64_t fsm_present_state : 7; + uint64_t reserved6 : 5; + uint64_t bad_array_address : 1; + uint64_t ecc_corrected_error : 1; + uint64_t ecc_uncorrected_error : 1; + uint64_t read_invalid : 1; + uint64_t write_invalid : 1; + uint64_t addr_invalid : 1; +#endif // _BIG_ENDIAN + } fields; +} pibmem_status_t; + + + +typedef union pibmem_reset { + + 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 reset_code : 2; + uint64_t _reserved0 : 62; +#else + uint64_t _reserved0 : 62; + uint64_t reset_code : 2; +#endif // _BIG_ENDIAN + } fields; +} pibmem_reset_t; + + + +typedef union pibmem_repair { + + 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; +} pibmem_repair_t; + + +#endif // __ASSEMBLER__ +#endif // __PIBMEM_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/pibmem_register_addresses.h b/src/ssx/pgp/registers/pibmem_register_addresses.h new file mode 100644 index 0000000..0cffaa2 --- /dev/null +++ b/src/ssx/pgp/registers/pibmem_register_addresses.h @@ -0,0 +1,30 @@ +#ifndef __PIBMEM_REGISTER_ADDRESSES_H__ +#define __PIBMEM_REGISTER_ADDRESSES_H__ + +// $Id: pibmem_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pibmem_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pibmem_register_addresses.h +/// \brief Symbolic addresses for the PIBMEM unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define PIBMEM_PIB_BASE 0x00080000 +#define PIBMEM_DATA0 0x00080000 +#define PIBMEM_CONTROL 0x00088000 +#define PIBMEM_ADDRESS 0x00088001 +#define PIBMEM_DATA 0x00088002 +#define PIBMEM_DATA_INC 0x00088003 +#define PIBMEM_DATA_DEC 0x00088004 +#define PIBMEM_STATUS 0x00088005 +#define PIBMEM_RESET 0x00088006 +#define PIBMEM_REPAIR 0x00088007 + +#endif // __PIBMEM_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/plb_arbiter_firmware_registers.h b/src/ssx/pgp/registers/plb_arbiter_firmware_registers.h new file mode 100755 index 0000000..583e95d --- /dev/null +++ b/src/ssx/pgp/registers/plb_arbiter_firmware_registers.h @@ -0,0 +1,215 @@ +#ifndef __PLB_ARBITER_FIRMWARE_REGISTERS_H__ +#define __PLB_ARBITER_FIRMWARE_REGISTERS_H__ + +// $Id: plb_arbiter_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/plb_arbiter_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file plb_arbiter_firmware_registers.h +/// \brief C register structs for the PLB_ARBITER unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union plb_prev { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t value : 32; +#else + uint32_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} plb_prev_t; + + + +typedef union plb_pacr { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t ppm : 1; + uint32_t ppo : 3; + uint32_t hbu : 1; + uint32_t rdp : 2; + uint32_t wrp : 1; + uint32_t _reserved0 : 24; +#else + uint32_t _reserved0 : 24; + uint32_t wrp : 1; + uint32_t rdp : 2; + uint32_t hbu : 1; + uint32_t ppo : 3; + uint32_t ppm : 1; +#endif // _BIG_ENDIAN + } fields; +} plb_pacr_t; + + + +typedef union plb_pesr { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t pte0 : 1; + uint32_t rw0 : 1; + uint32_t flk0 : 1; + uint32_t alk0 : 1; + uint32_t pte1 : 1; + uint32_t rw1 : 1; + uint32_t flk1 : 1; + uint32_t alk1 : 1; + uint32_t pte2 : 1; + uint32_t rw2 : 1; + uint32_t flk2 : 1; + uint32_t alk2 : 1; + uint32_t pte3 : 1; + uint32_t rw3 : 1; + uint32_t flk3 : 1; + uint32_t alk3 : 1; + uint32_t pte4 : 1; + uint32_t rw4 : 1; + uint32_t flk4 : 1; + uint32_t alk4 : 1; + uint32_t pte5 : 1; + uint32_t rw5 : 1; + uint32_t flk5 : 1; + uint32_t alk5 : 1; + uint32_t pte6 : 1; + uint32_t rw6 : 1; + uint32_t flk6 : 1; + uint32_t alk6 : 1; + uint32_t pte7 : 1; + uint32_t rw7 : 1; + uint32_t flk7 : 1; + uint32_t alk7 : 1; +#else + uint32_t alk7 : 1; + uint32_t flk7 : 1; + uint32_t rw7 : 1; + uint32_t pte7 : 1; + uint32_t alk6 : 1; + uint32_t flk6 : 1; + uint32_t rw6 : 1; + uint32_t pte6 : 1; + uint32_t alk5 : 1; + uint32_t flk5 : 1; + uint32_t rw5 : 1; + uint32_t pte5 : 1; + uint32_t alk4 : 1; + uint32_t flk4 : 1; + uint32_t rw4 : 1; + uint32_t pte4 : 1; + uint32_t alk3 : 1; + uint32_t flk3 : 1; + uint32_t rw3 : 1; + uint32_t pte3 : 1; + uint32_t alk2 : 1; + uint32_t flk2 : 1; + uint32_t rw2 : 1; + uint32_t pte2 : 1; + uint32_t alk1 : 1; + uint32_t flk1 : 1; + uint32_t rw1 : 1; + uint32_t pte1 : 1; + uint32_t alk0 : 1; + uint32_t flk0 : 1; + uint32_t rw0 : 1; + uint32_t pte0 : 1; +#endif // _BIG_ENDIAN + } fields; +} plb_pesr_t; + + + +typedef union plb_pearl { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t value : 32; +#else + uint32_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} plb_pearl_t; + + + +typedef union plb_pearh { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t value : 32; +#else + uint32_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} plb_pearh_t; + + + +typedef union plb_sto_pesr { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t icu_te : 1; + uint32_t icu_rw : 1; + uint32_t reserved2 : 2; + uint32_t dcu_te : 1; + uint32_t dcu_rw : 1; + uint32_t reserved6 : 2; + uint32_t _reserved0 : 24; +#else + uint32_t _reserved0 : 24; + uint32_t reserved6 : 2; + uint32_t dcu_rw : 1; + uint32_t dcu_te : 1; + uint32_t reserved2 : 2; + uint32_t icu_rw : 1; + uint32_t icu_te : 1; +#endif // _BIG_ENDIAN + } fields; +} plb_sto_pesr_t; + + + +typedef union plb_sto_pear { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t value : 32; +#else + uint32_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} plb_sto_pear_t; + + +#endif // __ASSEMBLER__ +#endif // __PLB_ARBITER_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/plb_arbiter_register_addresses.h b/src/ssx/pgp/registers/plb_arbiter_register_addresses.h new file mode 100755 index 0000000..2bc2f41 --- /dev/null +++ b/src/ssx/pgp/registers/plb_arbiter_register_addresses.h @@ -0,0 +1,28 @@ +#ifndef __PLB_ARBITER_REGISTER_ADDRESSES_H__ +#define __PLB_ARBITER_REGISTER_ADDRESSES_H__ + +// $Id: plb_arbiter_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:24 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/plb_arbiter_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file plb_arbiter_register_addresses.h +/// \brief Symbolic addresses for the PLB_ARBITER unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define PLB_DCR_BASE 0x90 +#define PLB_PREV 0x00000092 +#define PLB_PACR 0x00000093 +#define PLB_PESR 0x00000094 +#define PLB_PEARL 0x00000096 +#define PLB_PEARH 0x00000097 +#define PLB_STO_PESR 0x00000099 +#define PLB_STO_PEAR 0x00000098 + +#endif // __PLB_ARBITER_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/pmc_firmware_registers.h b/src/ssx/pgp/registers/pmc_firmware_registers.h new file mode 100755 index 0000000..76642a4 --- /dev/null +++ b/src/ssx/pgp/registers/pmc_firmware_registers.h @@ -0,0 +1,3140 @@ +#ifndef __PMC_FIRMWARE_REGISTERS_H__ +#define __PMC_FIRMWARE_REGISTERS_H__ + +// $Id: pmc_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pmc_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pmc_firmware_registers.h +/// \brief C register structs for the PMC unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union pmc_mode_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t enable_hw_pstate_mode : 1; + uint32_t enable_fw_auction_pstate_mode : 1; + uint32_t enable_fw_pstate_mode : 1; + uint32_t enable_pstate_voltage_changes : 1; + uint32_t enable_global_actual_pstate_forwarding : 1; + uint32_t halt_pstate_master_fsm : 1; + uint32_t enable_interchip_interface : 1; + uint32_t interchip_mode : 1; + uint32_t enable_interchip_pstate_in_haps : 1; + uint32_t enable_pstate_stepping : 1; + uint32_t honor_oha_idle_state_requests : 1; + uint32_t vid_endianess : 1; + uint32_t reset_all_pmc_registers : 1; + uint32_t safe_mode_without_spivid : 1; + uint32_t halt_idle_state_master_fsm : 1; + uint32_t interchip_halt_if : 1; + uint32_t unfreeze_pstate_processing : 1; + uint32_t spivid_reset_if : 1; + uint32_t unfreeze_istate_processing : 1; + uint32_t _reserved0 : 13; +#else + uint32_t _reserved0 : 13; + uint32_t unfreeze_istate_processing : 1; + uint32_t spivid_reset_if : 1; + uint32_t unfreeze_pstate_processing : 1; + uint32_t interchip_halt_if : 1; + uint32_t halt_idle_state_master_fsm : 1; + uint32_t safe_mode_without_spivid : 1; + uint32_t reset_all_pmc_registers : 1; + uint32_t vid_endianess : 1; + uint32_t honor_oha_idle_state_requests : 1; + uint32_t enable_pstate_stepping : 1; + uint32_t enable_interchip_pstate_in_haps : 1; + uint32_t interchip_mode : 1; + uint32_t enable_interchip_interface : 1; + uint32_t halt_pstate_master_fsm : 1; + uint32_t enable_global_actual_pstate_forwarding : 1; + uint32_t enable_pstate_voltage_changes : 1; + uint32_t enable_fw_pstate_mode : 1; + uint32_t enable_fw_auction_pstate_mode : 1; + uint32_t enable_hw_pstate_mode : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_mode_reg_t; + + + +typedef union pmc_hardware_auction_pstate_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + int32_t haps : 8; + uint32_t kuv_actual : 8; + uint32_t kuv_received : 8; + uint32_t _reserved0 : 8; +#else + uint32_t _reserved0 : 8; + uint32_t kuv_received : 8; + uint32_t kuv_actual : 8; + int32_t haps : 8; +#endif // _BIG_ENDIAN + } fields; +} pmc_hardware_auction_pstate_reg_t; + + + +typedef union pmc_pstate_monitor_and_ctrl_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + int32_t gpst_val : 8; + int32_t gpsst : 8; + int32_t gpsa : 8; + int32_t gapr : 8; +#else + int32_t gapr : 8; + int32_t gpsa : 8; + int32_t gpsst : 8; + int32_t gpst_val : 8; +#endif // _BIG_ENDIAN + } fields; +} pmc_pstate_monitor_and_ctrl_reg_t; + + + +typedef union pmc_rail_bounds_register { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + int32_t pmin_rail : 8; + int32_t pmax_rail : 8; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + int32_t pmax_rail : 8; + int32_t pmin_rail : 8; +#endif // _BIG_ENDIAN + } fields; +} pmc_rail_bounds_register_t; + + + +typedef union pmc_global_pstate_bounds_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t gpsi_min : 8; + uint32_t gpst_number_of_entries_minus_one : 7; + uint32_t _reserved0 : 17; +#else + uint32_t _reserved0 : 17; + uint32_t gpst_number_of_entries_minus_one : 7; + uint32_t gpsi_min : 8; +#endif // _BIG_ENDIAN + } fields; +} pmc_global_pstate_bounds_reg_t; + + + +typedef union pmc_parameter_reg0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t pstate_stepsize : 7; + uint32_t vrm_stepdelay_range : 4; + uint32_t vrm_stepdelay_value : 4; + uint32_t hangpulse_predivider : 6; + uint32_t gpsa_timeout_value : 8; + uint32_t gpsa_timeout_value_sel : 1; + uint32_t _reserved0 : 2; +#else + uint32_t _reserved0 : 2; + uint32_t gpsa_timeout_value_sel : 1; + uint32_t gpsa_timeout_value : 8; + uint32_t hangpulse_predivider : 6; + uint32_t vrm_stepdelay_value : 4; + uint32_t vrm_stepdelay_range : 4; + uint32_t pstate_stepsize : 7; +#endif // _BIG_ENDIAN + } fields; +} pmc_parameter_reg0_t; + + + +typedef union pmc_parameter_reg1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t ba_sram_pstate_table : 22; + int32_t pvsafe : 8; + uint32_t _reserved0 : 2; +#else + uint32_t _reserved0 : 2; + int32_t pvsafe : 8; + uint32_t ba_sram_pstate_table : 22; +#endif // _BIG_ENDIAN + } fields; +} pmc_parameter_reg1_t; + + + +typedef union pmc_eff_global_actual_voltage_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t maxreg_vdd : 8; + uint32_t maxreg_vcs : 8; + uint32_t eff_evid_vdd : 8; + uint32_t eff_evid_vcs : 8; +#else + uint32_t eff_evid_vcs : 8; + uint32_t eff_evid_vdd : 8; + uint32_t maxreg_vcs : 8; + uint32_t maxreg_vdd : 8; +#endif // _BIG_ENDIAN + } fields; +} pmc_eff_global_actual_voltage_reg_t; + + + +typedef union pmc_global_actual_voltage_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t evid_vdd : 8; + uint32_t evid_vcs : 8; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t evid_vcs : 8; + uint32_t evid_vdd : 8; +#endif // _BIG_ENDIAN + } fields; +} pmc_global_actual_voltage_reg_t; + + + +typedef union pmc_status_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t pstate_processing_is_suspended : 1; + uint32_t gpsa_bdcst_error : 1; + uint32_t gpsa_bdcst_resp_info : 3; + uint32_t gpsa_vchg_error : 1; + uint32_t gpsa_timeout_error : 1; + uint32_t gpsa_chg_ongoing : 1; + uint32_t volt_chg_ongoing : 1; + uint32_t brd_cst_ongoing : 1; + uint32_t gps_table_error : 1; + uint32_t pstate_interchip_error : 1; + uint32_t istate_processing_is_suspended : 1; + uint32_t safe_mode_engaged : 1; + uint32_t _reserved0 : 18; +#else + uint32_t _reserved0 : 18; + uint32_t safe_mode_engaged : 1; + uint32_t istate_processing_is_suspended : 1; + uint32_t pstate_interchip_error : 1; + uint32_t gps_table_error : 1; + uint32_t brd_cst_ongoing : 1; + uint32_t volt_chg_ongoing : 1; + uint32_t gpsa_chg_ongoing : 1; + uint32_t gpsa_timeout_error : 1; + uint32_t gpsa_vchg_error : 1; + uint32_t gpsa_bdcst_resp_info : 3; + uint32_t gpsa_bdcst_error : 1; + uint32_t pstate_processing_is_suspended : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_status_reg_t; + + + +typedef union pmc_phase_enable_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t phase_enable : 4; + uint32_t _reserved0 : 28; +#else + uint32_t _reserved0 : 28; + uint32_t phase_enable : 4; +#endif // _BIG_ENDIAN + } fields; +} pmc_phase_enable_reg_t; + + + +typedef union pmc_undervolting_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + int32_t puv_min : 8; + int32_t puv_max : 8; + uint32_t kuv_request : 8; + uint32_t _reserved0 : 8; +#else + uint32_t _reserved0 : 8; + uint32_t kuv_request : 8; + int32_t puv_max : 8; + int32_t puv_min : 8; +#endif // _BIG_ENDIAN + } fields; +} pmc_undervolting_reg_t; + + + +typedef union pmc_core_deconfiguration_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t core_chiplet_deconf_vector : 16; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t core_chiplet_deconf_vector : 16; +#endif // _BIG_ENDIAN + } fields; +} pmc_core_deconfiguration_reg_t; + + + +typedef union pmc_intchp_ctrl_reg1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t interchip_ga_fsm_enable : 1; + uint32_t interchip_recv_done_valid_without_if_en : 1; + uint32_t pmcic1_reserved_2 : 1; + uint32_t interchip_cpha : 1; + uint32_t interchip_clock_divider : 10; + uint32_t pmcicr1_reserved_14_17 : 4; + uint32_t pmcicr1_reserved_18_20 : 3; + uint32_t _reserved0 : 11; +#else + uint32_t _reserved0 : 11; + uint32_t pmcicr1_reserved_18_20 : 3; + uint32_t pmcicr1_reserved_14_17 : 4; + uint32_t interchip_clock_divider : 10; + uint32_t interchip_cpha : 1; + uint32_t pmcic1_reserved_2 : 1; + uint32_t interchip_recv_done_valid_without_if_en : 1; + uint32_t interchip_ga_fsm_enable : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_intchp_ctrl_reg1_t; + + + +typedef union pmc_intchp_ctrl_reg2 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t interchip_ping_send : 1; + uint32_t interchip_ping_detect_clear : 1; + uint32_t interchip_ping_mode : 1; + uint32_t pmcic2_reserved3 : 1; + uint32_t pmcic2_reserved4 : 1; + uint32_t pmcic2_reserved5_7 : 3; + uint32_t _reserved0 : 24; +#else + uint32_t _reserved0 : 24; + uint32_t pmcic2_reserved5_7 : 3; + uint32_t pmcic2_reserved4 : 1; + uint32_t pmcic2_reserved3 : 1; + uint32_t interchip_ping_mode : 1; + uint32_t interchip_ping_detect_clear : 1; + uint32_t interchip_ping_send : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_intchp_ctrl_reg2_t; + + + +typedef union pmc_intchp_ctrl_reg4 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t interchip_ecc_gen_en : 1; + uint32_t interchip_ecc_check_en : 1; + uint32_t interchip_msg_rcv_overflow_check_en : 1; + uint32_t interchip_ecc_ue_block_en : 1; + uint32_t chksw_hw221732 : 1; + uint32_t slave_occ_timeout_forces_safe_mode_disable : 1; + uint32_t pmcic4_reserved6_7 : 2; + uint32_t _reserved0 : 24; +#else + uint32_t _reserved0 : 24; + uint32_t pmcic4_reserved6_7 : 2; + uint32_t slave_occ_timeout_forces_safe_mode_disable : 1; + uint32_t chksw_hw221732 : 1; + uint32_t interchip_ecc_ue_block_en : 1; + uint32_t interchip_msg_rcv_overflow_check_en : 1; + uint32_t interchip_ecc_check_en : 1; + uint32_t interchip_ecc_gen_en : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_intchp_ctrl_reg4_t; + + + +typedef union pmc_intchp_status_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t interchip_ga_ongoing : 1; + uint32_t interchip_ecc_ue : 1; + uint32_t interchip_ecc_ce : 1; + uint32_t interchip_ping_detected : 1; + uint32_t interchip_ping_ack_detected : 1; + uint32_t interchip_msg_send_ongoing : 1; + uint32_t interchip_msg_recv_detected : 1; + uint32_t interchip_fsm_err : 1; + uint32_t interchip_ping_detect_count : 8; + uint32_t interchip_slave_error_code : 4; + uint32_t interchip_msg_snd_overflow_detected : 1; + uint32_t interchip_msg_rcv_overflow_detected : 1; + uint32_t interchip_ecc_ue_err : 1; + uint32_t _reserved0 : 9; +#else + uint32_t _reserved0 : 9; + uint32_t interchip_ecc_ue_err : 1; + uint32_t interchip_msg_rcv_overflow_detected : 1; + uint32_t interchip_msg_snd_overflow_detected : 1; + uint32_t interchip_slave_error_code : 4; + uint32_t interchip_ping_detect_count : 8; + uint32_t interchip_fsm_err : 1; + uint32_t interchip_msg_recv_detected : 1; + uint32_t interchip_msg_send_ongoing : 1; + uint32_t interchip_ping_ack_detected : 1; + uint32_t interchip_ping_detected : 1; + uint32_t interchip_ecc_ce : 1; + uint32_t interchip_ecc_ue : 1; + uint32_t interchip_ga_ongoing : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_intchp_status_reg_t; + + + +typedef union pmc_intchp_command_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t interchip_reset_if : 1; + uint32_t interchip_halt_msg_fsm : 1; + uint32_t interchip_clear_sticky_bits : 1; + uint32_t _reserved0 : 29; +#else + uint32_t _reserved0 : 29; + uint32_t interchip_clear_sticky_bits : 1; + uint32_t interchip_halt_msg_fsm : 1; + uint32_t interchip_reset_if : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_intchp_command_reg_t; + + + +typedef union pmc_intchp_msg_wdata { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t interchip_msg_wdata : 32; +#else + uint32_t interchip_msg_wdata : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_intchp_msg_wdata_t; + + + +typedef union pmc_intchp_msg_rdata { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t interchip_msg_rdata : 32; +#else + uint32_t interchip_msg_rdata : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_intchp_msg_rdata_t; + + + +typedef union pmc_intchp_pstate_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + int32_t pstate_interchip : 8; + uint32_t _reserved0 : 24; +#else + uint32_t _reserved0 : 24; + int32_t pstate_interchip : 8; +#endif // _BIG_ENDIAN + } fields; +} pmc_intchp_pstate_reg_t; + + + +typedef union pmc_intchp_globack_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t gaack_interchip : 1; + int32_t gaack_interchip_pstate : 8; + uint32_t _reserved0 : 23; +#else + uint32_t _reserved0 : 23; + int32_t gaack_interchip_pstate : 8; + uint32_t gaack_interchip : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_intchp_globack_reg_t; + + + +typedef union pmc_fsmstate_status_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t mis_fsm_state : 3; + uint32_t mps_fsm_state : 5; + uint32_t svs_fsm_state : 4; + uint32_t o2s_fsm_state : 4; + uint32_t m2p_fsm_state : 4; + uint32_t o2p_fsm_state : 4; + uint32_t icp_msg_fsm_state : 5; + uint32_t _reserved0 : 3; +#else + uint32_t _reserved0 : 3; + uint32_t icp_msg_fsm_state : 5; + uint32_t o2p_fsm_state : 4; + uint32_t m2p_fsm_state : 4; + uint32_t o2s_fsm_state : 4; + uint32_t svs_fsm_state : 4; + uint32_t mps_fsm_state : 5; + uint32_t mis_fsm_state : 3; +#endif // _BIG_ENDIAN + } fields; +} pmc_fsmstate_status_reg_t; + + + +typedef union pmc_trace_mode_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t pmc_trace_mode : 4; + uint32_t trace_sel_data : 2; + uint32_t _reserved0 : 26; +#else + uint32_t _reserved0 : 26; + uint32_t trace_sel_data : 2; + uint32_t pmc_trace_mode : 4; +#endif // _BIG_ENDIAN + } fields; +} pmc_trace_mode_reg_t; + + + +typedef union pmc_spiv_ctrl_reg0a { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t spivid_frame_size : 6; + uint32_t spivid_out_count1 : 6; + uint32_t spivid_in_delay1 : 6; + uint32_t spivid_in_count1 : 6; + uint32_t _reserved0 : 8; +#else + uint32_t _reserved0 : 8; + uint32_t spivid_in_count1 : 6; + uint32_t spivid_in_delay1 : 6; + uint32_t spivid_out_count1 : 6; + uint32_t spivid_frame_size : 6; +#endif // _BIG_ENDIAN + } fields; +} pmc_spiv_ctrl_reg0a_t; + + + +typedef union pmc_spiv_ctrl_reg0b { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t spivid_out_count2 : 6; + uint32_t spivid_in_delay2 : 6; + uint32_t spivid_in_count2 : 6; + uint32_t _reserved0 : 14; +#else + uint32_t _reserved0 : 14; + uint32_t spivid_in_count2 : 6; + uint32_t spivid_in_delay2 : 6; + uint32_t spivid_out_count2 : 6; +#endif // _BIG_ENDIAN + } fields; +} pmc_spiv_ctrl_reg0b_t; + + + +typedef union pmc_spiv_ctrl_reg1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t spivid_fsm_enable : 1; + uint32_t pmcscr1_reserved_1 : 1; + uint32_t spivid_cpol : 1; + uint32_t spivid_cpha : 1; + uint32_t spivid_clock_divider : 10; + uint32_t pmcscr1_reserved_2 : 4; + uint32_t spivid_port_enable : 3; + uint32_t _reserved0 : 11; +#else + uint32_t _reserved0 : 11; + uint32_t spivid_port_enable : 3; + uint32_t pmcscr1_reserved_2 : 4; + uint32_t spivid_clock_divider : 10; + uint32_t spivid_cpha : 1; + uint32_t spivid_cpol : 1; + uint32_t pmcscr1_reserved_1 : 1; + uint32_t spivid_fsm_enable : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_spiv_ctrl_reg1_t; + + + +typedef union pmc_spiv_ctrl_reg2 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t spivid_inter_frame_delay_write_status : 17; + uint32_t _reserved0 : 15; +#else + uint32_t _reserved0 : 15; + uint32_t spivid_inter_frame_delay_write_status : 17; +#endif // _BIG_ENDIAN + } fields; +} pmc_spiv_ctrl_reg2_t; + + + +typedef union pmc_spiv_ctrl_reg3 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t spivid_inter_retry_delay : 17; + uint32_t pmc_100ns_pls_range : 6; + uint32_t _reserved0 : 9; +#else + uint32_t _reserved0 : 9; + uint32_t pmc_100ns_pls_range : 6; + uint32_t spivid_inter_retry_delay : 17; +#endif // _BIG_ENDIAN + } fields; +} pmc_spiv_ctrl_reg3_t; + + + +typedef union pmc_spiv_ctrl_reg4 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t spivid_crc_gen_en : 1; + uint32_t spivid_crc_check_en : 1; + uint32_t spivid_majority_vote_en : 1; + uint32_t spivid_max_retries : 5; + uint32_t spivid_crc_polynomial_enables : 8; + uint32_t spivid_crc_const_gen_enable : 1; + uint32_t spivid_crc_const_check_enable : 1; + uint32_t spivid_frame_sync_wrong_enable : 1; + uint32_t _reserved0 : 13; +#else + uint32_t _reserved0 : 13; + uint32_t spivid_frame_sync_wrong_enable : 1; + uint32_t spivid_crc_const_check_enable : 1; + uint32_t spivid_crc_const_gen_enable : 1; + uint32_t spivid_crc_polynomial_enables : 8; + uint32_t spivid_max_retries : 5; + uint32_t spivid_majority_vote_en : 1; + uint32_t spivid_crc_check_en : 1; + uint32_t spivid_crc_gen_en : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_spiv_ctrl_reg4_t; + + + +typedef union pmc_spiv_status_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t spivid_ongoing : 1; + uint32_t spivid_crc_error0 : 1; + uint32_t spivid_crc_error1 : 1; + uint32_t spivid_crc_error2 : 1; + uint32_t spivid_retry_timeout : 1; + uint32_t pmcssr_reserved_1 : 2; + uint32_t spivid_fsm_err : 1; + uint32_t spivid_majority_detected_a_minority0 : 1; + uint32_t spivid_majority_detected_a_minority1 : 1; + uint32_t spivid_majority_detected_a_minority2 : 1; + uint32_t spivid_majority_nr_of_minorities0 : 4; + uint32_t spivid_majority_nr_of_minorities1 : 4; + uint32_t spivid_majority_nr_of_minorities2 : 4; + uint32_t _reserved0 : 9; +#else + uint32_t _reserved0 : 9; + uint32_t spivid_majority_nr_of_minorities2 : 4; + uint32_t spivid_majority_nr_of_minorities1 : 4; + uint32_t spivid_majority_nr_of_minorities0 : 4; + uint32_t spivid_majority_detected_a_minority2 : 1; + uint32_t spivid_majority_detected_a_minority1 : 1; + uint32_t spivid_majority_detected_a_minority0 : 1; + uint32_t spivid_fsm_err : 1; + uint32_t pmcssr_reserved_1 : 2; + uint32_t spivid_retry_timeout : 1; + uint32_t spivid_crc_error2 : 1; + uint32_t spivid_crc_error1 : 1; + uint32_t spivid_crc_error0 : 1; + uint32_t spivid_ongoing : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_spiv_status_reg_t; + + + +typedef union pmc_spiv_command_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t spivid_halt_fsm : 1; + uint32_t _reserved0 : 31; +#else + uint32_t _reserved0 : 31; + uint32_t spivid_halt_fsm : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_spiv_command_reg_t; + + + +typedef union pmc_o2s_ctrl_reg0a { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t o2s_frame_size : 6; + uint32_t o2s_out_count1 : 6; + uint32_t o2s_in_delay1 : 6; + uint32_t o2s_in_count1 : 6; + uint32_t _reserved0 : 8; +#else + uint32_t _reserved0 : 8; + uint32_t o2s_in_count1 : 6; + uint32_t o2s_in_delay1 : 6; + uint32_t o2s_out_count1 : 6; + uint32_t o2s_frame_size : 6; +#endif // _BIG_ENDIAN + } fields; +} pmc_o2s_ctrl_reg0a_t; + + + +typedef union pmc_o2s_ctrl_reg0b { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t o2s_out_count2 : 6; + uint32_t o2s_in_delay2 : 6; + uint32_t o2s_in_count2 : 6; + uint32_t _reserved0 : 14; +#else + uint32_t _reserved0 : 14; + uint32_t o2s_in_count2 : 6; + uint32_t o2s_in_delay2 : 6; + uint32_t o2s_out_count2 : 6; +#endif // _BIG_ENDIAN + } fields; +} pmc_o2s_ctrl_reg0b_t; + + + +typedef union pmc_o2s_ctrl_reg1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t o2s_bridge_enable : 1; + uint32_t pmcocr1_reserved_1 : 1; + uint32_t o2s_cpol : 1; + uint32_t o2s_cpha : 1; + uint32_t o2s_clock_divider : 10; + uint32_t pmcocr1_reserved_2 : 3; + uint32_t o2s_nr_of_frames : 1; + uint32_t o2s_port_enable : 3; + uint32_t _reserved0 : 11; +#else + uint32_t _reserved0 : 11; + uint32_t o2s_port_enable : 3; + uint32_t o2s_nr_of_frames : 1; + uint32_t pmcocr1_reserved_2 : 3; + uint32_t o2s_clock_divider : 10; + uint32_t o2s_cpha : 1; + uint32_t o2s_cpol : 1; + uint32_t pmcocr1_reserved_1 : 1; + uint32_t o2s_bridge_enable : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_o2s_ctrl_reg1_t; + + + +typedef union pmc_o2s_ctrl_reg2 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t o2s_inter_frame_delay : 17; + uint32_t _reserved0 : 15; +#else + uint32_t _reserved0 : 15; + uint32_t o2s_inter_frame_delay : 17; +#endif // _BIG_ENDIAN + } fields; +} pmc_o2s_ctrl_reg2_t; + + + +typedef union pmc_o2s_ctrl_reg4 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t o2s_crc_gen_en : 1; + uint32_t o2s_crc_check_en : 1; + uint32_t o2s_majority_vote_en : 1; + uint32_t o2s_max_retries : 5; + uint32_t pmcocr4_reserved8_15 : 8; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t pmcocr4_reserved8_15 : 8; + uint32_t o2s_max_retries : 5; + uint32_t o2s_majority_vote_en : 1; + uint32_t o2s_crc_check_en : 1; + uint32_t o2s_crc_gen_en : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_o2s_ctrl_reg4_t; + + + +typedef union pmc_o2s_status_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t o2s_ongoing : 1; + uint32_t o2s_crc_error0 : 1; + uint32_t o2s_crc_error1 : 1; + uint32_t o2s_crc_error2 : 1; + uint32_t o2s_retry_timeout : 1; + uint32_t o2s_write_while_bridge_busy_err : 1; + uint32_t pmcosr_reserved_6 : 1; + uint32_t o2s_fsm_err : 1; + uint32_t o2s_majority_detected_a_minority0 : 1; + uint32_t o2s_majority_detected_a_minority1 : 1; + uint32_t o2s_majority_detected_a_minority2 : 1; + uint32_t o2s_majority_nr_of_minorities0 : 4; + uint32_t o2s_majority_nr_of_minorities1 : 4; + uint32_t o2s_majority_nr_of_minorities2 : 4; + uint32_t _reserved0 : 9; +#else + uint32_t _reserved0 : 9; + uint32_t o2s_majority_nr_of_minorities2 : 4; + uint32_t o2s_majority_nr_of_minorities1 : 4; + uint32_t o2s_majority_nr_of_minorities0 : 4; + uint32_t o2s_majority_detected_a_minority2 : 1; + uint32_t o2s_majority_detected_a_minority1 : 1; + uint32_t o2s_majority_detected_a_minority0 : 1; + uint32_t o2s_fsm_err : 1; + uint32_t pmcosr_reserved_6 : 1; + uint32_t o2s_write_while_bridge_busy_err : 1; + uint32_t o2s_retry_timeout : 1; + uint32_t o2s_crc_error2 : 1; + uint32_t o2s_crc_error1 : 1; + uint32_t o2s_crc_error0 : 1; + uint32_t o2s_ongoing : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_o2s_status_reg_t; + + + +typedef union pmc_o2s_command_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t o2s_halt_retries : 1; + uint32_t o2s_clear_sticky_bits : 1; + uint32_t _reserved0 : 30; +#else + uint32_t _reserved0 : 30; + uint32_t o2s_clear_sticky_bits : 1; + uint32_t o2s_halt_retries : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_o2s_command_reg_t; + + + +typedef union pmc_o2s_wdata_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t o2s_wdata : 32; +#else + uint32_t o2s_wdata : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_o2s_wdata_reg_t; + + + +typedef union pmc_o2s_rdata_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t o2s_rdata : 32; +#else + uint32_t o2s_rdata : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_o2s_rdata_reg_t; + + + +typedef union pmc_o2p_addr_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t o2p_write_plus_read : 1; + uint32_t o2p_mc : 1; + uint32_t o2p_slave_addr : 6; + uint32_t o2p_read_not_write : 1; + uint32_t reserved_bit_pmco2par2 : 3; + uint32_t o2p_pcb_port : 4; + uint32_t o2p_pcb_reg_addr : 16; +#else + uint32_t o2p_pcb_reg_addr : 16; + uint32_t o2p_pcb_port : 4; + uint32_t reserved_bit_pmco2par2 : 3; + uint32_t o2p_read_not_write : 1; + uint32_t o2p_slave_addr : 6; + uint32_t o2p_mc : 1; + uint32_t o2p_write_plus_read : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_o2p_addr_reg_t; + + + +typedef union pmc_o2p_ctrl_status_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t o2p_ongoing : 1; + uint32_t o2p_scresp : 3; + uint32_t o2p_write_while_bridge_busy_err : 1; + uint32_t o2p_fsm_err : 1; + uint32_t o2p_abort : 1; + uint32_t o2p_parity_error : 1; + uint32_t o2p_clear_sticky_bits : 1; + uint32_t _reserved0 : 23; +#else + uint32_t _reserved0 : 23; + uint32_t o2p_clear_sticky_bits : 1; + uint32_t o2p_parity_error : 1; + uint32_t o2p_abort : 1; + uint32_t o2p_fsm_err : 1; + uint32_t o2p_write_while_bridge_busy_err : 1; + uint32_t o2p_scresp : 3; + uint32_t o2p_ongoing : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_o2p_ctrl_status_reg_t; + + + +typedef union pmc_o2p_send_data_hi_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t o2p_send_data_hi : 32; +#else + uint32_t o2p_send_data_hi : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_o2p_send_data_hi_reg_t; + + + +typedef union pmc_o2p_send_data_lo_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t o2p_send_data_lo : 32; +#else + uint32_t o2p_send_data_lo : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_o2p_send_data_lo_reg_t; + + + +typedef union pmc_o2p_recv_data_hi_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t o2p_receive_data_hi : 32; +#else + uint32_t o2p_receive_data_hi : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_o2p_recv_data_hi_reg_t; + + + +typedef union pmc_o2p_recv_data_lo_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t o2p_receive_data_lo : 32; +#else + uint32_t o2p_receive_data_lo : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_o2p_recv_data_lo_reg_t; + + + +typedef union pmc_occ_heartbeat_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t pmc_occ_heartbeat_time : 16; + uint32_t pmc_occ_heartbeat_en : 1; + uint32_t _reserved0 : 15; +#else + uint32_t _reserved0 : 15; + uint32_t pmc_occ_heartbeat_en : 1; + uint32_t pmc_occ_heartbeat_time : 16; +#endif // _BIG_ENDIAN + } fields; +} pmc_occ_heartbeat_reg_t; + + + +typedef union pmc_error_int_mask_hi_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t pmc_error_int_mask_hi : 32; +#else + uint32_t pmc_error_int_mask_hi : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_error_int_mask_hi_reg_t; + + + +typedef union pmc_error_int_mask_lo_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t pmc_error_int_mask_lo : 32; +#else + uint32_t pmc_error_int_mask_lo : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_error_int_mask_lo_reg_t; + + + +typedef union pmc_idle_suspend_mask_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t pmc_idle_suspend_mask : 16; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t pmc_idle_suspend_mask : 16; +#endif // _BIG_ENDIAN + } fields; +} pmc_idle_suspend_mask_reg_t; + + + +typedef union pmc_pend_idle_req_reg0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t idle_pending_0 : 1; + uint32_t idle_op_0 : 2; + uint32_t idle_type_0 : 1; + uint32_t idle_scope_0 : 1; + uint32_t assist_mode_0 : 1; + uint32_t reserved_pirr_0 : 2; + uint32_t idle_pending_1 : 1; + uint32_t idle_op_1 : 2; + uint32_t idle_type_1 : 1; + uint32_t idle_scope_1 : 1; + uint32_t assist_mode_1 : 1; + uint32_t reserved_pirr_1 : 2; + uint32_t idle_pending_2 : 1; + uint32_t idle_op_2 : 2; + uint32_t idle_type_2 : 1; + uint32_t idle_scope_2 : 1; + uint32_t assist_mode_2 : 1; + uint32_t reserved_pirr_2 : 2; + uint32_t idle_pending_3 : 1; + uint32_t idle_op_3 : 2; + uint32_t idle_type_3 : 1; + uint32_t idle_scope_3 : 1; + uint32_t assist_mode_3 : 1; + uint32_t reserved_pirr_3 : 2; +#else + uint32_t reserved_pirr_3 : 2; + uint32_t assist_mode_3 : 1; + uint32_t idle_scope_3 : 1; + uint32_t idle_type_3 : 1; + uint32_t idle_op_3 : 2; + uint32_t idle_pending_3 : 1; + uint32_t reserved_pirr_2 : 2; + uint32_t assist_mode_2 : 1; + uint32_t idle_scope_2 : 1; + uint32_t idle_type_2 : 1; + uint32_t idle_op_2 : 2; + uint32_t idle_pending_2 : 1; + uint32_t reserved_pirr_1 : 2; + uint32_t assist_mode_1 : 1; + uint32_t idle_scope_1 : 1; + uint32_t idle_type_1 : 1; + uint32_t idle_op_1 : 2; + uint32_t idle_pending_1 : 1; + uint32_t reserved_pirr_0 : 2; + uint32_t assist_mode_0 : 1; + uint32_t idle_scope_0 : 1; + uint32_t idle_type_0 : 1; + uint32_t idle_op_0 : 2; + uint32_t idle_pending_0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_pend_idle_req_reg0_t; + + + +typedef union pmc_pend_idle_req_reg1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t idle_pending_4 : 1; + uint32_t idle_op_4 : 2; + uint32_t idle_type_4 : 1; + uint32_t idle_scope_4 : 1; + uint32_t assist_mode_4 : 1; + uint32_t reserved_pirr_4 : 2; + uint32_t idle_pending_5 : 1; + uint32_t idle_op_5 : 2; + uint32_t idle_type_5 : 1; + uint32_t idle_scope_5 : 1; + uint32_t assist_mode_5 : 1; + uint32_t reserved_pirr_5 : 2; + uint32_t idle_pending_6 : 1; + uint32_t idle_op_6 : 2; + uint32_t idle_type_6 : 1; + uint32_t idle_scope_6 : 1; + uint32_t assist_mode_6 : 1; + uint32_t reserved_pirr_6 : 2; + uint32_t idle_pending_7 : 1; + uint32_t idle_op_7 : 2; + uint32_t idle_type_7 : 1; + uint32_t idle_scope_7 : 1; + uint32_t assist_mode_7 : 1; + uint32_t reserved_pirr_7 : 2; +#else + uint32_t reserved_pirr_7 : 2; + uint32_t assist_mode_7 : 1; + uint32_t idle_scope_7 : 1; + uint32_t idle_type_7 : 1; + uint32_t idle_op_7 : 2; + uint32_t idle_pending_7 : 1; + uint32_t reserved_pirr_6 : 2; + uint32_t assist_mode_6 : 1; + uint32_t idle_scope_6 : 1; + uint32_t idle_type_6 : 1; + uint32_t idle_op_6 : 2; + uint32_t idle_pending_6 : 1; + uint32_t reserved_pirr_5 : 2; + uint32_t assist_mode_5 : 1; + uint32_t idle_scope_5 : 1; + uint32_t idle_type_5 : 1; + uint32_t idle_op_5 : 2; + uint32_t idle_pending_5 : 1; + uint32_t reserved_pirr_4 : 2; + uint32_t assist_mode_4 : 1; + uint32_t idle_scope_4 : 1; + uint32_t idle_type_4 : 1; + uint32_t idle_op_4 : 2; + uint32_t idle_pending_4 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_pend_idle_req_reg1_t; + + + +typedef union pmc_pend_idle_req_reg2 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t idle_pending_8 : 1; + uint32_t idle_op_8 : 2; + uint32_t idle_type_8 : 1; + uint32_t idle_scope_8 : 1; + uint32_t assist_mode_8 : 1; + uint32_t reserved_pirr_8 : 2; + uint32_t idle_pending_9 : 1; + uint32_t idle_op_9 : 2; + uint32_t idle_type_9 : 1; + uint32_t idle_scope_9 : 1; + uint32_t assist_mode_9 : 1; + uint32_t reserved_pirr_9 : 2; + uint32_t idle_pending_10 : 1; + uint32_t idle_op_10 : 2; + uint32_t idle_type_10 : 1; + uint32_t idle_scope_10 : 1; + uint32_t assist_mode_10 : 1; + uint32_t reserved_pirr_10 : 2; + uint32_t idle_pending_11 : 1; + uint32_t idle_op_11 : 2; + uint32_t idle_type_11 : 1; + uint32_t idle_scope_11 : 1; + uint32_t assist_mode_11 : 1; + uint32_t reserved_pirr_11 : 2; +#else + uint32_t reserved_pirr_11 : 2; + uint32_t assist_mode_11 : 1; + uint32_t idle_scope_11 : 1; + uint32_t idle_type_11 : 1; + uint32_t idle_op_11 : 2; + uint32_t idle_pending_11 : 1; + uint32_t reserved_pirr_10 : 2; + uint32_t assist_mode_10 : 1; + uint32_t idle_scope_10 : 1; + uint32_t idle_type_10 : 1; + uint32_t idle_op_10 : 2; + uint32_t idle_pending_10 : 1; + uint32_t reserved_pirr_9 : 2; + uint32_t assist_mode_9 : 1; + uint32_t idle_scope_9 : 1; + uint32_t idle_type_9 : 1; + uint32_t idle_op_9 : 2; + uint32_t idle_pending_9 : 1; + uint32_t reserved_pirr_8 : 2; + uint32_t assist_mode_8 : 1; + uint32_t idle_scope_8 : 1; + uint32_t idle_type_8 : 1; + uint32_t idle_op_8 : 2; + uint32_t idle_pending_8 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_pend_idle_req_reg2_t; + + + +typedef union pmc_pend_idle_req_reg3 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t idle_pending_12 : 1; + uint32_t idle_op_12 : 2; + uint32_t idle_type_12 : 1; + uint32_t idle_scope_12 : 1; + uint32_t assist_mode_12 : 1; + uint32_t reserved_pirr_12 : 2; + uint32_t idle_pending_13 : 1; + uint32_t idle_op_13 : 2; + uint32_t idle_type_13 : 1; + uint32_t idle_scope_13 : 1; + uint32_t assist_mode_13 : 1; + uint32_t reserved_pirr_13 : 2; + uint32_t idle_pending_14 : 1; + uint32_t idle_op_14 : 2; + uint32_t idle_type_14 : 1; + uint32_t idle_scope_14 : 1; + uint32_t assist_mode_14 : 1; + uint32_t reserved_pirr_14 : 2; + uint32_t idle_pending_15 : 1; + uint32_t idle_op_15 : 2; + uint32_t idle_type_15 : 1; + uint32_t idle_scope_15 : 1; + uint32_t assist_mode_15 : 1; + uint32_t reserved_pirr_15 : 2; +#else + uint32_t reserved_pirr_15 : 2; + uint32_t assist_mode_15 : 1; + uint32_t idle_scope_15 : 1; + uint32_t idle_type_15 : 1; + uint32_t idle_op_15 : 2; + uint32_t idle_pending_15 : 1; + uint32_t reserved_pirr_14 : 2; + uint32_t assist_mode_14 : 1; + uint32_t idle_scope_14 : 1; + uint32_t idle_type_14 : 1; + uint32_t idle_op_14 : 2; + uint32_t idle_pending_14 : 1; + uint32_t reserved_pirr_13 : 2; + uint32_t assist_mode_13 : 1; + uint32_t idle_scope_13 : 1; + uint32_t idle_type_13 : 1; + uint32_t idle_op_13 : 2; + uint32_t idle_pending_13 : 1; + uint32_t reserved_pirr_12 : 2; + uint32_t assist_mode_12 : 1; + uint32_t idle_scope_12 : 1; + uint32_t idle_type_12 : 1; + uint32_t idle_op_12 : 2; + uint32_t idle_pending_12 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_pend_idle_req_reg3_t; + + + +typedef union pmc_sleep_int_req_vec_reg0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t fastsleepentry_int_req_vec : 32; +#else + uint32_t fastsleepentry_int_req_vec : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_sleep_int_req_vec_reg0_t; + + + +typedef union pmc_sleep_int_req_vec_reg1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t deepsleepentry_int_req_vec : 32; +#else + uint32_t deepsleepentry_int_req_vec : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_sleep_int_req_vec_reg1_t; + + + +typedef union pmc_sleep_int_req_vec_reg2 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t fastsleepexit_int_req_vec : 32; +#else + uint32_t fastsleepexit_int_req_vec : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_sleep_int_req_vec_reg2_t; + + + +typedef union pmc_sleep_int_req_vec_reg3 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t deepsleepexit_int_req_vec : 32; +#else + uint32_t deepsleepexit_int_req_vec : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_sleep_int_req_vec_reg3_t; + + + +typedef union pmc_winkle_int_req_vec_reg0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t fastwinkleentry_int_req_vec : 32; +#else + uint32_t fastwinkleentry_int_req_vec : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_winkle_int_req_vec_reg0_t; + + + +typedef union pmc_winkle_int_req_vec_reg1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t deepwinkleentry_int_req_vec : 32; +#else + uint32_t deepwinkleentry_int_req_vec : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_winkle_int_req_vec_reg1_t; + + + +typedef union pmc_winkle_int_req_vec_reg2 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t fastwinkleexit_int_req_vec : 32; +#else + uint32_t fastwinkleexit_int_req_vec : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_winkle_int_req_vec_reg2_t; + + + +typedef union pmc_winkle_int_req_vec_reg3 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t deepwinkleexit_int_req_vec : 32; +#else + uint32_t deepwinkleexit_int_req_vec : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_winkle_int_req_vec_reg3_t; + + + +typedef union pmc_nap_int_req_vec_reg0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t napentry_int_req_vec : 16; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t napentry_int_req_vec : 16; +#endif // _BIG_ENDIAN + } fields; +} pmc_nap_int_req_vec_reg0_t; + + + +typedef union pmc_nap_int_req_vec_reg1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t napexit_int_req_vec : 25; + uint32_t _reserved0 : 7; +#else + uint32_t _reserved0 : 7; + uint32_t napexit_int_req_vec : 25; +#endif // _BIG_ENDIAN + } fields; +} pmc_nap_int_req_vec_reg1_t; + + + +typedef union pmc_pore_req_reg0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t porrr_reserved0 : 8; + uint32_t porrr_start_vector : 4; + uint32_t porrr_reserved1 : 8; + uint32_t porrr_pore_busy : 1; + uint32_t porrr_pore_suspended : 1; + uint32_t porrr_porrtc_busy : 1; + uint32_t _reserved0 : 9; +#else + uint32_t _reserved0 : 9; + uint32_t porrr_porrtc_busy : 1; + uint32_t porrr_pore_suspended : 1; + uint32_t porrr_pore_busy : 1; + uint32_t porrr_reserved1 : 8; + uint32_t porrr_start_vector : 4; + uint32_t porrr_reserved0 : 8; +#endif // _BIG_ENDIAN + } fields; +} pmc_pore_req_reg0_t; + + + +typedef union pmc_pore_req_reg1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t porrr_chiplet_enable_0 : 1; + uint32_t porrr_chiplet_enable_1 : 1; + uint32_t porrr_chiplet_enable_2 : 1; + uint32_t porrr_chiplet_enable_3 : 1; + uint32_t porrr_chiplet_enable_4 : 1; + uint32_t porrr_chiplet_enable_5 : 1; + uint32_t porrr_chiplet_enable_6 : 1; + uint32_t porrr_chiplet_enable_7 : 1; + uint32_t porrr_chiplet_enable_8 : 1; + uint32_t porrr_chiplet_enable_9 : 1; + uint32_t porrr_chiplet_enable_10 : 1; + uint32_t porrr_chiplet_enable_11 : 1; + uint32_t porrr_chiplet_enable_12 : 1; + uint32_t porrr_chiplet_enable_13 : 1; + uint32_t porrr_chiplet_enable_14 : 1; + uint32_t porrr_chiplet_enable_15 : 1; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t porrr_chiplet_enable_15 : 1; + uint32_t porrr_chiplet_enable_14 : 1; + uint32_t porrr_chiplet_enable_13 : 1; + uint32_t porrr_chiplet_enable_12 : 1; + uint32_t porrr_chiplet_enable_11 : 1; + uint32_t porrr_chiplet_enable_10 : 1; + uint32_t porrr_chiplet_enable_9 : 1; + uint32_t porrr_chiplet_enable_8 : 1; + uint32_t porrr_chiplet_enable_7 : 1; + uint32_t porrr_chiplet_enable_6 : 1; + uint32_t porrr_chiplet_enable_5 : 1; + uint32_t porrr_chiplet_enable_4 : 1; + uint32_t porrr_chiplet_enable_3 : 1; + uint32_t porrr_chiplet_enable_2 : 1; + uint32_t porrr_chiplet_enable_1 : 1; + uint32_t porrr_chiplet_enable_0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_pore_req_reg1_t; + + + +typedef union pmc_pore_req_stat_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t porrs_reserved0 : 8; + uint32_t porrs_start_vector : 4; + uint32_t pore_rc : 8; + uint32_t porrs_reserved1 : 1; + uint32_t porrs_recovery_write : 1; + uint32_t _reserved0 : 10; +#else + uint32_t _reserved0 : 10; + uint32_t porrs_recovery_write : 1; + uint32_t porrs_reserved1 : 1; + uint32_t pore_rc : 8; + uint32_t porrs_start_vector : 4; + uint32_t porrs_reserved0 : 8; +#endif // _BIG_ENDIAN + } fields; +} pmc_pore_req_stat_reg_t; + + + +typedef union pmc_pore_req_tout_th_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t porrtt_timeout_threshold : 8; + uint32_t porrtc_no_predivide : 1; + uint32_t _reserved0 : 23; +#else + uint32_t _reserved0 : 23; + uint32_t porrtc_no_predivide : 1; + uint32_t porrtt_timeout_threshold : 8; +#endif // _BIG_ENDIAN + } fields; +} pmc_pore_req_tout_th_reg_t; + + + +typedef union pmc_deep_exit_mask_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t chiplet_deep_exit_mask0 : 1; + uint32_t chiplet_deep_exit_mask1 : 1; + uint32_t chiplet_deep_exit_mask2 : 1; + uint32_t chiplet_deep_exit_mask3 : 1; + uint32_t chiplet_deep_exit_mask4 : 1; + uint32_t chiplet_deep_exit_mask5 : 1; + uint32_t chiplet_deep_exit_mask6 : 1; + uint32_t chiplet_deep_exit_mask7 : 1; + uint32_t chiplet_deep_exit_mask8 : 1; + uint32_t chiplet_deep_exit_mask9 : 1; + uint32_t chiplet_deep_exit_mask10 : 1; + uint32_t chiplet_deep_exit_mask11 : 1; + uint32_t chiplet_deep_exit_mask12 : 1; + uint32_t chiplet_deep_exit_mask13 : 1; + uint32_t chiplet_deep_exit_mask14 : 1; + uint32_t chiplet_deep_exit_mask15 : 1; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t chiplet_deep_exit_mask15 : 1; + uint32_t chiplet_deep_exit_mask14 : 1; + uint32_t chiplet_deep_exit_mask13 : 1; + uint32_t chiplet_deep_exit_mask12 : 1; + uint32_t chiplet_deep_exit_mask11 : 1; + uint32_t chiplet_deep_exit_mask10 : 1; + uint32_t chiplet_deep_exit_mask9 : 1; + uint32_t chiplet_deep_exit_mask8 : 1; + uint32_t chiplet_deep_exit_mask7 : 1; + uint32_t chiplet_deep_exit_mask6 : 1; + uint32_t chiplet_deep_exit_mask5 : 1; + uint32_t chiplet_deep_exit_mask4 : 1; + uint32_t chiplet_deep_exit_mask3 : 1; + uint32_t chiplet_deep_exit_mask2 : 1; + uint32_t chiplet_deep_exit_mask1 : 1; + uint32_t chiplet_deep_exit_mask0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_deep_exit_mask_reg_t; + + + +typedef union pmc_deep_exit_mask_reg_and { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t chiplet_deep_exit_mask0 : 1; + uint32_t chiplet_deep_exit_mask1 : 1; + uint32_t chiplet_deep_exit_mask2 : 1; + uint32_t chiplet_deep_exit_mask3 : 1; + uint32_t chiplet_deep_exit_mask4 : 1; + uint32_t chiplet_deep_exit_mask5 : 1; + uint32_t chiplet_deep_exit_mask6 : 1; + uint32_t chiplet_deep_exit_mask7 : 1; + uint32_t chiplet_deep_exit_mask8 : 1; + uint32_t chiplet_deep_exit_mask9 : 1; + uint32_t chiplet_deep_exit_mask10 : 1; + uint32_t chiplet_deep_exit_mask11 : 1; + uint32_t chiplet_deep_exit_mask12 : 1; + uint32_t chiplet_deep_exit_mask13 : 1; + uint32_t chiplet_deep_exit_mask14 : 1; + uint32_t chiplet_deep_exit_mask15 : 1; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t chiplet_deep_exit_mask15 : 1; + uint32_t chiplet_deep_exit_mask14 : 1; + uint32_t chiplet_deep_exit_mask13 : 1; + uint32_t chiplet_deep_exit_mask12 : 1; + uint32_t chiplet_deep_exit_mask11 : 1; + uint32_t chiplet_deep_exit_mask10 : 1; + uint32_t chiplet_deep_exit_mask9 : 1; + uint32_t chiplet_deep_exit_mask8 : 1; + uint32_t chiplet_deep_exit_mask7 : 1; + uint32_t chiplet_deep_exit_mask6 : 1; + uint32_t chiplet_deep_exit_mask5 : 1; + uint32_t chiplet_deep_exit_mask4 : 1; + uint32_t chiplet_deep_exit_mask3 : 1; + uint32_t chiplet_deep_exit_mask2 : 1; + uint32_t chiplet_deep_exit_mask1 : 1; + uint32_t chiplet_deep_exit_mask0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_deep_exit_mask_reg_and_t; + + + +typedef union pmc_deep_exit_mask_reg_or { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t chiplet_deep_exit_mask0 : 1; + uint32_t chiplet_deep_exit_mask1 : 1; + uint32_t chiplet_deep_exit_mask2 : 1; + uint32_t chiplet_deep_exit_mask3 : 1; + uint32_t chiplet_deep_exit_mask4 : 1; + uint32_t chiplet_deep_exit_mask5 : 1; + uint32_t chiplet_deep_exit_mask6 : 1; + uint32_t chiplet_deep_exit_mask7 : 1; + uint32_t chiplet_deep_exit_mask8 : 1; + uint32_t chiplet_deep_exit_mask9 : 1; + uint32_t chiplet_deep_exit_mask10 : 1; + uint32_t chiplet_deep_exit_mask11 : 1; + uint32_t chiplet_deep_exit_mask12 : 1; + uint32_t chiplet_deep_exit_mask13 : 1; + uint32_t chiplet_deep_exit_mask14 : 1; + uint32_t chiplet_deep_exit_mask15 : 1; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t chiplet_deep_exit_mask15 : 1; + uint32_t chiplet_deep_exit_mask14 : 1; + uint32_t chiplet_deep_exit_mask13 : 1; + uint32_t chiplet_deep_exit_mask12 : 1; + uint32_t chiplet_deep_exit_mask11 : 1; + uint32_t chiplet_deep_exit_mask10 : 1; + uint32_t chiplet_deep_exit_mask9 : 1; + uint32_t chiplet_deep_exit_mask8 : 1; + uint32_t chiplet_deep_exit_mask7 : 1; + uint32_t chiplet_deep_exit_mask6 : 1; + uint32_t chiplet_deep_exit_mask5 : 1; + uint32_t chiplet_deep_exit_mask4 : 1; + uint32_t chiplet_deep_exit_mask3 : 1; + uint32_t chiplet_deep_exit_mask2 : 1; + uint32_t chiplet_deep_exit_mask1 : 1; + uint32_t chiplet_deep_exit_mask0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_deep_exit_mask_reg_or_t; + + + +typedef union pmc_core_pstate_reg0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + int32_t pstate_core0 : 8; + int32_t pstate_core1 : 8; + int32_t pstate_core2 : 8; + int32_t pstate_core3 : 8; +#else + int32_t pstate_core3 : 8; + int32_t pstate_core2 : 8; + int32_t pstate_core1 : 8; + int32_t pstate_core0 : 8; +#endif // _BIG_ENDIAN + } fields; +} pmc_core_pstate_reg0_t; + + + +typedef union pmc_core_pstate_reg1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + int32_t pstate_core4 : 8; + int32_t pstate_core5 : 8; + int32_t pstate_core6 : 8; + int32_t pstate_core7 : 8; +#else + int32_t pstate_core7 : 8; + int32_t pstate_core6 : 8; + int32_t pstate_core5 : 8; + int32_t pstate_core4 : 8; +#endif // _BIG_ENDIAN + } fields; +} pmc_core_pstate_reg1_t; + + + +typedef union pmc_core_pstate_reg2 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + int32_t pstate_core8 : 8; + int32_t pstate_core9 : 8; + int32_t pstate_core10 : 8; + int32_t pstate_core11 : 8; +#else + int32_t pstate_core11 : 8; + int32_t pstate_core10 : 8; + int32_t pstate_core9 : 8; + int32_t pstate_core8 : 8; +#endif // _BIG_ENDIAN + } fields; +} pmc_core_pstate_reg2_t; + + + +typedef union pmc_core_pstate_reg3 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + int32_t pstate_core12 : 8; + int32_t pstate_core13 : 8; + int32_t pstate_core14 : 8; + int32_t pstate_core15 : 8; +#else + int32_t pstate_core15 : 8; + int32_t pstate_core14 : 8; + int32_t pstate_core13 : 8; + int32_t pstate_core12 : 8; +#endif // _BIG_ENDIAN + } fields; +} pmc_core_pstate_reg3_t; + + + +typedef union pmc_core_power_donation_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t power_donation_core0 : 1; + uint32_t power_donation_core1 : 1; + uint32_t power_donation_core2 : 1; + uint32_t power_donation_core3 : 1; + uint32_t power_donation_core4 : 1; + uint32_t power_donation_core5 : 1; + uint32_t power_donation_core6 : 1; + uint32_t power_donation_core7 : 1; + uint32_t power_donation_core8 : 1; + uint32_t power_donation_core9 : 1; + uint32_t power_donation_core10 : 1; + uint32_t power_donation_core11 : 1; + uint32_t power_donation_core12 : 1; + uint32_t power_donation_core13 : 1; + uint32_t power_donation_core14 : 1; + uint32_t power_donation_core15 : 1; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t power_donation_core15 : 1; + uint32_t power_donation_core14 : 1; + uint32_t power_donation_core13 : 1; + uint32_t power_donation_core12 : 1; + uint32_t power_donation_core11 : 1; + uint32_t power_donation_core10 : 1; + uint32_t power_donation_core9 : 1; + uint32_t power_donation_core8 : 1; + uint32_t power_donation_core7 : 1; + uint32_t power_donation_core6 : 1; + uint32_t power_donation_core5 : 1; + uint32_t power_donation_core4 : 1; + uint32_t power_donation_core3 : 1; + uint32_t power_donation_core2 : 1; + uint32_t power_donation_core1 : 1; + uint32_t power_donation_core0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_core_power_donation_reg_t; + + + +typedef union pmc_pmax_sync_collection_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t pmax_sync0 : 1; + uint32_t pmax_sync1 : 1; + uint32_t pmax_sync2 : 1; + uint32_t pmax_sync3 : 1; + uint32_t pmax_sync4 : 1; + uint32_t pmax_sync5 : 1; + uint32_t pmax_sync6 : 1; + uint32_t pmax_sync7 : 1; + uint32_t pmax_sync8 : 1; + uint32_t pmax_sync9 : 1; + uint32_t pmax_sync10 : 1; + uint32_t pmax_sync11 : 1; + uint32_t pmax_sync12 : 1; + uint32_t pmax_sync13 : 1; + uint32_t pmax_sync14 : 1; + uint32_t pmax_sync15 : 1; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t pmax_sync15 : 1; + uint32_t pmax_sync14 : 1; + uint32_t pmax_sync13 : 1; + uint32_t pmax_sync12 : 1; + uint32_t pmax_sync11 : 1; + uint32_t pmax_sync10 : 1; + uint32_t pmax_sync9 : 1; + uint32_t pmax_sync8 : 1; + uint32_t pmax_sync7 : 1; + uint32_t pmax_sync6 : 1; + uint32_t pmax_sync5 : 1; + uint32_t pmax_sync4 : 1; + uint32_t pmax_sync3 : 1; + uint32_t pmax_sync2 : 1; + uint32_t pmax_sync1 : 1; + uint32_t pmax_sync0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_pmax_sync_collection_reg_t; + + + +typedef union pmc_pmax_sync_collection_mask_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t pmax_sync_mask0 : 1; + uint32_t pmax_sync_mask1 : 1; + uint32_t pmax_sync_mask2 : 1; + uint32_t pmax_sync_mask3 : 1; + uint32_t pmax_sync_mask4 : 1; + uint32_t pmax_sync_mask5 : 1; + uint32_t pmax_sync_mask6 : 1; + uint32_t pmax_sync_mask7 : 1; + uint32_t pmax_sync_mask8 : 1; + uint32_t pmax_sync_mask9 : 1; + uint32_t pmax_sync_mask10 : 1; + uint32_t pmax_sync_mask11 : 1; + uint32_t pmax_sync_mask12 : 1; + uint32_t pmax_sync_mask13 : 1; + uint32_t pmax_sync_mask14 : 1; + uint32_t pmax_sync_mask15 : 1; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t pmax_sync_mask15 : 1; + uint32_t pmax_sync_mask14 : 1; + uint32_t pmax_sync_mask13 : 1; + uint32_t pmax_sync_mask12 : 1; + uint32_t pmax_sync_mask11 : 1; + uint32_t pmax_sync_mask10 : 1; + uint32_t pmax_sync_mask9 : 1; + uint32_t pmax_sync_mask8 : 1; + uint32_t pmax_sync_mask7 : 1; + uint32_t pmax_sync_mask6 : 1; + uint32_t pmax_sync_mask5 : 1; + uint32_t pmax_sync_mask4 : 1; + uint32_t pmax_sync_mask3 : 1; + uint32_t pmax_sync_mask2 : 1; + uint32_t pmax_sync_mask1 : 1; + uint32_t pmax_sync_mask0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_pmax_sync_collection_mask_reg_t; + + + +typedef union pmc_gpsa_ack_collection_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t gpsa_ack0 : 1; + uint32_t gpsa_ack1 : 1; + uint32_t gpsa_ack2 : 1; + uint32_t gpsa_ack3 : 1; + uint32_t gpsa_ack4 : 1; + uint32_t gpsa_ack5 : 1; + uint32_t gpsa_ack6 : 1; + uint32_t gpsa_ack7 : 1; + uint32_t gpsa_ack8 : 1; + uint32_t gpsa_ack9 : 1; + uint32_t gpsa_ack10 : 1; + uint32_t gpsa_ack11 : 1; + uint32_t gpsa_ack12 : 1; + uint32_t gpsa_ack13 : 1; + uint32_t gpsa_ack14 : 1; + uint32_t gpsa_ack15 : 1; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t gpsa_ack15 : 1; + uint32_t gpsa_ack14 : 1; + uint32_t gpsa_ack13 : 1; + uint32_t gpsa_ack12 : 1; + uint32_t gpsa_ack11 : 1; + uint32_t gpsa_ack10 : 1; + uint32_t gpsa_ack9 : 1; + uint32_t gpsa_ack8 : 1; + uint32_t gpsa_ack7 : 1; + uint32_t gpsa_ack6 : 1; + uint32_t gpsa_ack5 : 1; + uint32_t gpsa_ack4 : 1; + uint32_t gpsa_ack3 : 1; + uint32_t gpsa_ack2 : 1; + uint32_t gpsa_ack1 : 1; + uint32_t gpsa_ack0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_gpsa_ack_collection_reg_t; + + + +typedef union pmc_gpsa_ack_collection_mask_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t gpsa_ack_mask0 : 1; + uint32_t gpsa_ack_mask1 : 1; + uint32_t gpsa_ack_mask2 : 1; + uint32_t gpsa_ack_mask3 : 1; + uint32_t gpsa_ack_mask4 : 1; + uint32_t gpsa_ack_mask5 : 1; + uint32_t gpsa_ack_mask6 : 1; + uint32_t gpsa_ack_mask7 : 1; + uint32_t gpsa_ack_mask8 : 1; + uint32_t gpsa_ack_mask9 : 1; + uint32_t gpsa_ack_mask10 : 1; + uint32_t gpsa_ack_mask11 : 1; + uint32_t gpsa_ack_mask12 : 1; + uint32_t gpsa_ack_mask13 : 1; + uint32_t gpsa_ack_mask14 : 1; + uint32_t gpsa_ack_mask15 : 1; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t gpsa_ack_mask15 : 1; + uint32_t gpsa_ack_mask14 : 1; + uint32_t gpsa_ack_mask13 : 1; + uint32_t gpsa_ack_mask12 : 1; + uint32_t gpsa_ack_mask11 : 1; + uint32_t gpsa_ack_mask10 : 1; + uint32_t gpsa_ack_mask9 : 1; + uint32_t gpsa_ack_mask8 : 1; + uint32_t gpsa_ack_mask7 : 1; + uint32_t gpsa_ack_mask6 : 1; + uint32_t gpsa_ack_mask5 : 1; + uint32_t gpsa_ack_mask4 : 1; + uint32_t gpsa_ack_mask3 : 1; + uint32_t gpsa_ack_mask2 : 1; + uint32_t gpsa_ack_mask1 : 1; + uint32_t gpsa_ack_mask0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_gpsa_ack_collection_mask_reg_t; + + + +typedef union pmc_pore_scratch_reg0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t porscr_scratch0 : 32; +#else + uint32_t porscr_scratch0 : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_pore_scratch_reg0_t; + + + +typedef union pmc_pore_scratch_reg1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t porscr_scratch1 : 32; +#else + uint32_t porscr_scratch1 : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_pore_scratch_reg1_t; + + + +typedef union pmc_deep_idle_exit_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t deep_exit_pending_and_masked_0 : 1; + uint32_t deep_exit_pending_and_masked_1 : 1; + uint32_t deep_exit_pending_and_masked_2 : 1; + uint32_t deep_exit_pending_and_masked_3 : 1; + uint32_t deep_exit_pending_and_masked_4 : 1; + uint32_t deep_exit_pending_and_masked_5 : 1; + uint32_t deep_exit_pending_and_masked_6 : 1; + uint32_t deep_exit_pending_and_masked_7 : 1; + uint32_t deep_exit_pending_and_masked_8 : 1; + uint32_t deep_exit_pending_and_masked_9 : 1; + uint32_t deep_exit_pending_and_masked_10 : 1; + uint32_t deep_exit_pending_and_masked_11 : 1; + uint32_t deep_exit_pending_and_masked_12 : 1; + uint32_t deep_exit_pending_and_masked_13 : 1; + uint32_t deep_exit_pending_and_masked_14 : 1; + uint32_t deep_exit_pending_and_masked_15 : 1; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t deep_exit_pending_and_masked_15 : 1; + uint32_t deep_exit_pending_and_masked_14 : 1; + uint32_t deep_exit_pending_and_masked_13 : 1; + uint32_t deep_exit_pending_and_masked_12 : 1; + uint32_t deep_exit_pending_and_masked_11 : 1; + uint32_t deep_exit_pending_and_masked_10 : 1; + uint32_t deep_exit_pending_and_masked_9 : 1; + uint32_t deep_exit_pending_and_masked_8 : 1; + uint32_t deep_exit_pending_and_masked_7 : 1; + uint32_t deep_exit_pending_and_masked_6 : 1; + uint32_t deep_exit_pending_and_masked_5 : 1; + uint32_t deep_exit_pending_and_masked_4 : 1; + uint32_t deep_exit_pending_and_masked_3 : 1; + uint32_t deep_exit_pending_and_masked_2 : 1; + uint32_t deep_exit_pending_and_masked_1 : 1; + uint32_t deep_exit_pending_and_masked_0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_deep_idle_exit_reg_t; + + + +typedef union pmc_deep_status_reg { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t deep_idle_state_core0 : 1; + uint32_t deep_idle_state_core1 : 1; + uint32_t deep_idle_state_core2 : 1; + uint32_t deep_idle_state_core3 : 1; + uint32_t deep_idle_state_core4 : 1; + uint32_t deep_idle_state_core5 : 1; + uint32_t deep_idle_state_core6 : 1; + uint32_t deep_idle_state_core7 : 1; + uint32_t deep_idle_state_core8 : 1; + uint32_t deep_idle_state_core9 : 1; + uint32_t deep_idle_state_core10 : 1; + uint32_t deep_idle_state_core11 : 1; + uint32_t deep_idle_state_core12 : 1; + uint32_t deep_idle_state_core13 : 1; + uint32_t deep_idle_state_core14 : 1; + uint32_t deep_idle_state_core15 : 1; + uint32_t winkle_state_core0 : 1; + uint32_t winkle_state_core1 : 1; + uint32_t winkle_state_core2 : 1; + uint32_t winkle_state_core3 : 1; + uint32_t winkle_state_core4 : 1; + uint32_t winkle_state_core5 : 1; + uint32_t winkle_state_core6 : 1; + uint32_t winkle_state_core7 : 1; + uint32_t winkle_state_core8 : 1; + uint32_t winkle_state_core9 : 1; + uint32_t winkle_state_core10 : 1; + uint32_t winkle_state_core11 : 1; + uint32_t winkle_state_core12 : 1; + uint32_t winkle_state_core13 : 1; + uint32_t winkle_state_core14 : 1; + uint32_t winkle_state_core15 : 1; +#else + uint32_t winkle_state_core15 : 1; + uint32_t winkle_state_core14 : 1; + uint32_t winkle_state_core13 : 1; + uint32_t winkle_state_core12 : 1; + uint32_t winkle_state_core11 : 1; + uint32_t winkle_state_core10 : 1; + uint32_t winkle_state_core9 : 1; + uint32_t winkle_state_core8 : 1; + uint32_t winkle_state_core7 : 1; + uint32_t winkle_state_core6 : 1; + uint32_t winkle_state_core5 : 1; + uint32_t winkle_state_core4 : 1; + uint32_t winkle_state_core3 : 1; + uint32_t winkle_state_core2 : 1; + uint32_t winkle_state_core1 : 1; + uint32_t winkle_state_core0 : 1; + uint32_t deep_idle_state_core15 : 1; + uint32_t deep_idle_state_core14 : 1; + uint32_t deep_idle_state_core13 : 1; + uint32_t deep_idle_state_core12 : 1; + uint32_t deep_idle_state_core11 : 1; + uint32_t deep_idle_state_core10 : 1; + uint32_t deep_idle_state_core9 : 1; + uint32_t deep_idle_state_core8 : 1; + uint32_t deep_idle_state_core7 : 1; + uint32_t deep_idle_state_core6 : 1; + uint32_t deep_idle_state_core5 : 1; + uint32_t deep_idle_state_core4 : 1; + uint32_t deep_idle_state_core3 : 1; + uint32_t deep_idle_state_core2 : 1; + uint32_t deep_idle_state_core1 : 1; + uint32_t deep_idle_state_core0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_deep_status_reg_t; + + + +typedef union pmc_ba_pore_exe_trigger_reg { + + 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 : 32; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_ba_pore_exe_trigger_reg_t; + + + +typedef union pmc_pcbs_gaps_brdcast_addr { + + 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 : 32; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t value : 32; +#endif // _BIG_ENDIAN + } fields; +} pmc_pcbs_gaps_brdcast_addr_t; + + + +typedef union pmc_lfir_err_reg { + + 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 lfir_pstate_oci_master_rderr : 1; + uint64_t lfir_pstate_oci_master_rddata_parity_err : 1; + uint64_t lfir_pstate_gpst_checkbyte_err : 1; + uint64_t lfir_pstate_gack_to_err : 1; + uint64_t lfir_pstate_pib_master_nonoffline_err : 1; + uint64_t lfir_pstate_pib_master_offline_err : 1; + uint64_t lfir_pstate_oci_master_to_err : 1; + uint64_t lfir_pstate_interchip_ue_err : 1; + uint64_t lfir_pstate_interchip_errorframe_err : 1; + uint64_t lfir_pstate_ms_fsm_err : 1; + uint64_t lfir_ms_comp_parity_err : 1; + uint64_t lfir_idle_poresw_fatal_err : 1; + uint64_t lfir_idle_poresw_status_rc_err : 1; + uint64_t lfir_idle_poresw_status_value_err : 1; + uint64_t lfir_idle_poresw_write_while_inactive_err : 1; + uint64_t lfir_idle_poresw_timeout_err : 1; + uint64_t lfir_idle_oci_master_write_timeout_err : 1; + uint64_t lfir_idle_internal_err : 1; + uint64_t lfir_int_comp_parity_err : 1; + uint64_t lfir_pmc_occ_heartbeat_timeout : 1; + uint64_t lfir_spivid_crc_error0 : 1; + uint64_t lfir_spivid_crc_error1 : 1; + uint64_t lfir_spivid_crc_error2 : 1; + uint64_t lfir_spivid_retry_timeout : 1; + uint64_t lfir_spivid_fsm_err : 1; + uint64_t lfir_spivid_majority_detected_a_minority : 1; + uint64_t lfir_o2s_crc_error0 : 1; + uint64_t lfir_o2s_crc_error1 : 1; + uint64_t lfir_o2s_crc_error2 : 1; + uint64_t lfir_o2s_retry_timeout : 1; + uint64_t lfir_o2s_write_while_bridge_busy_err : 1; + uint64_t lfir_o2s_fsm_err : 1; + uint64_t lfir_o2s_majority_detected_a_minority : 1; + uint64_t lfir_o2p_write_while_bridge_busy_err : 1; + uint64_t lfir_o2p_fsm_err : 1; + uint64_t lfir_oci_slave_err : 1; + uint64_t lfir_if_comp_parity_error : 1; + uint64_t spare_fir : 10; + uint64_t fir_parity_err_dup : 1; + uint64_t fir_parity_err : 1; + uint64_t _reserved0 : 15; +#else + uint64_t _reserved0 : 15; + uint64_t fir_parity_err : 1; + uint64_t fir_parity_err_dup : 1; + uint64_t spare_fir : 10; + uint64_t lfir_if_comp_parity_error : 1; + uint64_t lfir_oci_slave_err : 1; + uint64_t lfir_o2p_fsm_err : 1; + uint64_t lfir_o2p_write_while_bridge_busy_err : 1; + uint64_t lfir_o2s_majority_detected_a_minority : 1; + uint64_t lfir_o2s_fsm_err : 1; + uint64_t lfir_o2s_write_while_bridge_busy_err : 1; + uint64_t lfir_o2s_retry_timeout : 1; + uint64_t lfir_o2s_crc_error2 : 1; + uint64_t lfir_o2s_crc_error1 : 1; + uint64_t lfir_o2s_crc_error0 : 1; + uint64_t lfir_spivid_majority_detected_a_minority : 1; + uint64_t lfir_spivid_fsm_err : 1; + uint64_t lfir_spivid_retry_timeout : 1; + uint64_t lfir_spivid_crc_error2 : 1; + uint64_t lfir_spivid_crc_error1 : 1; + uint64_t lfir_spivid_crc_error0 : 1; + uint64_t lfir_pmc_occ_heartbeat_timeout : 1; + uint64_t lfir_int_comp_parity_err : 1; + uint64_t lfir_idle_internal_err : 1; + uint64_t lfir_idle_oci_master_write_timeout_err : 1; + uint64_t lfir_idle_poresw_timeout_err : 1; + uint64_t lfir_idle_poresw_write_while_inactive_err : 1; + uint64_t lfir_idle_poresw_status_value_err : 1; + uint64_t lfir_idle_poresw_status_rc_err : 1; + uint64_t lfir_idle_poresw_fatal_err : 1; + uint64_t lfir_ms_comp_parity_err : 1; + uint64_t lfir_pstate_ms_fsm_err : 1; + uint64_t lfir_pstate_interchip_errorframe_err : 1; + uint64_t lfir_pstate_interchip_ue_err : 1; + uint64_t lfir_pstate_oci_master_to_err : 1; + uint64_t lfir_pstate_pib_master_offline_err : 1; + uint64_t lfir_pstate_pib_master_nonoffline_err : 1; + uint64_t lfir_pstate_gack_to_err : 1; + uint64_t lfir_pstate_gpst_checkbyte_err : 1; + uint64_t lfir_pstate_oci_master_rddata_parity_err : 1; + uint64_t lfir_pstate_oci_master_rderr : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_lfir_err_reg_t; + + + +typedef union pmc_lfir_err_reg_and { + + 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 lfir_pstate_oci_master_rderr : 1; + uint64_t lfir_pstate_oci_master_rddata_parity_err : 1; + uint64_t lfir_pstate_gpst_checkbyte_err : 1; + uint64_t lfir_pstate_gack_to_err : 1; + uint64_t lfir_pstate_pib_master_nonoffline_err : 1; + uint64_t lfir_pstate_pib_master_offline_err : 1; + uint64_t lfir_pstate_oci_master_to_err : 1; + uint64_t lfir_pstate_interchip_ue_err : 1; + uint64_t lfir_pstate_interchip_errorframe_err : 1; + uint64_t lfir_pstate_ms_fsm_err : 1; + uint64_t lfir_ms_comp_parity_err : 1; + uint64_t lfir_idle_poresw_fatal_err : 1; + uint64_t lfir_idle_poresw_status_rc_err : 1; + uint64_t lfir_idle_poresw_status_value_err : 1; + uint64_t lfir_idle_poresw_write_while_inactive_err : 1; + uint64_t lfir_idle_poresw_timeout_err : 1; + uint64_t lfir_idle_oci_master_write_timeout_err : 1; + uint64_t lfir_idle_internal_err : 1; + uint64_t lfir_int_comp_parity_err : 1; + uint64_t lfir_pmc_occ_heartbeat_timeout : 1; + uint64_t lfir_spivid_crc_error0 : 1; + uint64_t lfir_spivid_crc_error1 : 1; + uint64_t lfir_spivid_crc_error2 : 1; + uint64_t lfir_spivid_retry_timeout : 1; + uint64_t lfir_spivid_fsm_err : 1; + uint64_t lfir_spivid_majority_detected_a_minority : 1; + uint64_t lfir_o2s_crc_error0 : 1; + uint64_t lfir_o2s_crc_error1 : 1; + uint64_t lfir_o2s_crc_error2 : 1; + uint64_t lfir_o2s_retry_timeout : 1; + uint64_t lfir_o2s_write_while_bridge_busy_err : 1; + uint64_t lfir_o2s_fsm_err : 1; + uint64_t lfir_o2s_majority_detected_a_minority : 1; + uint64_t lfir_o2p_write_while_bridge_busy_err : 1; + uint64_t lfir_o2p_fsm_err : 1; + uint64_t lfir_oci_slave_err : 1; + uint64_t lfir_if_comp_parity_error : 1; + uint64_t spare_fir : 10; + uint64_t fir_parity_err_dup : 1; + uint64_t fir_parity_err : 1; + uint64_t _reserved0 : 15; +#else + uint64_t _reserved0 : 15; + uint64_t fir_parity_err : 1; + uint64_t fir_parity_err_dup : 1; + uint64_t spare_fir : 10; + uint64_t lfir_if_comp_parity_error : 1; + uint64_t lfir_oci_slave_err : 1; + uint64_t lfir_o2p_fsm_err : 1; + uint64_t lfir_o2p_write_while_bridge_busy_err : 1; + uint64_t lfir_o2s_majority_detected_a_minority : 1; + uint64_t lfir_o2s_fsm_err : 1; + uint64_t lfir_o2s_write_while_bridge_busy_err : 1; + uint64_t lfir_o2s_retry_timeout : 1; + uint64_t lfir_o2s_crc_error2 : 1; + uint64_t lfir_o2s_crc_error1 : 1; + uint64_t lfir_o2s_crc_error0 : 1; + uint64_t lfir_spivid_majority_detected_a_minority : 1; + uint64_t lfir_spivid_fsm_err : 1; + uint64_t lfir_spivid_retry_timeout : 1; + uint64_t lfir_spivid_crc_error2 : 1; + uint64_t lfir_spivid_crc_error1 : 1; + uint64_t lfir_spivid_crc_error0 : 1; + uint64_t lfir_pmc_occ_heartbeat_timeout : 1; + uint64_t lfir_int_comp_parity_err : 1; + uint64_t lfir_idle_internal_err : 1; + uint64_t lfir_idle_oci_master_write_timeout_err : 1; + uint64_t lfir_idle_poresw_timeout_err : 1; + uint64_t lfir_idle_poresw_write_while_inactive_err : 1; + uint64_t lfir_idle_poresw_status_value_err : 1; + uint64_t lfir_idle_poresw_status_rc_err : 1; + uint64_t lfir_idle_poresw_fatal_err : 1; + uint64_t lfir_ms_comp_parity_err : 1; + uint64_t lfir_pstate_ms_fsm_err : 1; + uint64_t lfir_pstate_interchip_errorframe_err : 1; + uint64_t lfir_pstate_interchip_ue_err : 1; + uint64_t lfir_pstate_oci_master_to_err : 1; + uint64_t lfir_pstate_pib_master_offline_err : 1; + uint64_t lfir_pstate_pib_master_nonoffline_err : 1; + uint64_t lfir_pstate_gack_to_err : 1; + uint64_t lfir_pstate_gpst_checkbyte_err : 1; + uint64_t lfir_pstate_oci_master_rddata_parity_err : 1; + uint64_t lfir_pstate_oci_master_rderr : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_lfir_err_reg_and_t; + + + +typedef union pmc_lfir_err_reg_or { + + 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 lfir_pstate_oci_master_rderr : 1; + uint64_t lfir_pstate_oci_master_rddata_parity_err : 1; + uint64_t lfir_pstate_gpst_checkbyte_err : 1; + uint64_t lfir_pstate_gack_to_err : 1; + uint64_t lfir_pstate_pib_master_nonoffline_err : 1; + uint64_t lfir_pstate_pib_master_offline_err : 1; + uint64_t lfir_pstate_oci_master_to_err : 1; + uint64_t lfir_pstate_interchip_ue_err : 1; + uint64_t lfir_pstate_interchip_errorframe_err : 1; + uint64_t lfir_pstate_ms_fsm_err : 1; + uint64_t lfir_ms_comp_parity_err : 1; + uint64_t lfir_idle_poresw_fatal_err : 1; + uint64_t lfir_idle_poresw_status_rc_err : 1; + uint64_t lfir_idle_poresw_status_value_err : 1; + uint64_t lfir_idle_poresw_write_while_inactive_err : 1; + uint64_t lfir_idle_poresw_timeout_err : 1; + uint64_t lfir_idle_oci_master_write_timeout_err : 1; + uint64_t lfir_idle_internal_err : 1; + uint64_t lfir_int_comp_parity_err : 1; + uint64_t lfir_pmc_occ_heartbeat_timeout : 1; + uint64_t lfir_spivid_crc_error0 : 1; + uint64_t lfir_spivid_crc_error1 : 1; + uint64_t lfir_spivid_crc_error2 : 1; + uint64_t lfir_spivid_retry_timeout : 1; + uint64_t lfir_spivid_fsm_err : 1; + uint64_t lfir_spivid_majority_detected_a_minority : 1; + uint64_t lfir_o2s_crc_error0 : 1; + uint64_t lfir_o2s_crc_error1 : 1; + uint64_t lfir_o2s_crc_error2 : 1; + uint64_t lfir_o2s_retry_timeout : 1; + uint64_t lfir_o2s_write_while_bridge_busy_err : 1; + uint64_t lfir_o2s_fsm_err : 1; + uint64_t lfir_o2s_majority_detected_a_minority : 1; + uint64_t lfir_o2p_write_while_bridge_busy_err : 1; + uint64_t lfir_o2p_fsm_err : 1; + uint64_t lfir_oci_slave_err : 1; + uint64_t lfir_if_comp_parity_error : 1; + uint64_t spare_fir : 10; + uint64_t fir_parity_err_dup : 1; + uint64_t fir_parity_err : 1; + uint64_t _reserved0 : 15; +#else + uint64_t _reserved0 : 15; + uint64_t fir_parity_err : 1; + uint64_t fir_parity_err_dup : 1; + uint64_t spare_fir : 10; + uint64_t lfir_if_comp_parity_error : 1; + uint64_t lfir_oci_slave_err : 1; + uint64_t lfir_o2p_fsm_err : 1; + uint64_t lfir_o2p_write_while_bridge_busy_err : 1; + uint64_t lfir_o2s_majority_detected_a_minority : 1; + uint64_t lfir_o2s_fsm_err : 1; + uint64_t lfir_o2s_write_while_bridge_busy_err : 1; + uint64_t lfir_o2s_retry_timeout : 1; + uint64_t lfir_o2s_crc_error2 : 1; + uint64_t lfir_o2s_crc_error1 : 1; + uint64_t lfir_o2s_crc_error0 : 1; + uint64_t lfir_spivid_majority_detected_a_minority : 1; + uint64_t lfir_spivid_fsm_err : 1; + uint64_t lfir_spivid_retry_timeout : 1; + uint64_t lfir_spivid_crc_error2 : 1; + uint64_t lfir_spivid_crc_error1 : 1; + uint64_t lfir_spivid_crc_error0 : 1; + uint64_t lfir_pmc_occ_heartbeat_timeout : 1; + uint64_t lfir_int_comp_parity_err : 1; + uint64_t lfir_idle_internal_err : 1; + uint64_t lfir_idle_oci_master_write_timeout_err : 1; + uint64_t lfir_idle_poresw_timeout_err : 1; + uint64_t lfir_idle_poresw_write_while_inactive_err : 1; + uint64_t lfir_idle_poresw_status_value_err : 1; + uint64_t lfir_idle_poresw_status_rc_err : 1; + uint64_t lfir_idle_poresw_fatal_err : 1; + uint64_t lfir_ms_comp_parity_err : 1; + uint64_t lfir_pstate_ms_fsm_err : 1; + uint64_t lfir_pstate_interchip_errorframe_err : 1; + uint64_t lfir_pstate_interchip_ue_err : 1; + uint64_t lfir_pstate_oci_master_to_err : 1; + uint64_t lfir_pstate_pib_master_offline_err : 1; + uint64_t lfir_pstate_pib_master_nonoffline_err : 1; + uint64_t lfir_pstate_gack_to_err : 1; + uint64_t lfir_pstate_gpst_checkbyte_err : 1; + uint64_t lfir_pstate_oci_master_rddata_parity_err : 1; + uint64_t lfir_pstate_oci_master_rderr : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_lfir_err_reg_or_t; + + + +typedef union pmc_lfir_err_mask_reg { + + 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 pmc_lfir_mask_0 : 1; + uint64_t pmc_lfir_mask_1 : 1; + uint64_t pmc_lfir_mask_2 : 1; + uint64_t pmc_lfir_mask_3 : 1; + uint64_t pmc_lfir_mask_4 : 1; + uint64_t pmc_lfir_mask_5 : 1; + uint64_t pmc_lfir_mask_6 : 1; + uint64_t pmc_lfir_mask_7 : 1; + uint64_t pmc_lfir_mask_8 : 1; + uint64_t pmc_lfir_mask_9 : 1; + uint64_t pmc_lfir_mask_10 : 1; + uint64_t pmc_lfir_mask_11 : 1; + uint64_t pmc_lfir_mask_12 : 1; + uint64_t pmc_lfir_mask_13 : 1; + uint64_t pmc_lfir_mask_14 : 1; + uint64_t pmc_lfir_mask_15 : 1; + uint64_t pmc_lfir_mask_16 : 1; + uint64_t pmc_lfir_mask_17 : 1; + uint64_t pmc_lfir_mask_18 : 1; + uint64_t pmc_lfir_mask_19 : 1; + uint64_t pmc_lfir_mask_20 : 1; + uint64_t pmc_lfir_mask_21 : 1; + uint64_t pmc_lfir_mask_22 : 1; + uint64_t pmc_lfir_mask_23 : 1; + uint64_t pmc_lfir_mask_24 : 1; + uint64_t pmc_lfir_mask_25 : 1; + uint64_t pmc_lfir_mask_26 : 1; + uint64_t pmc_lfir_mask_27 : 1; + uint64_t pmc_lfir_mask_28 : 1; + uint64_t pmc_lfir_mask_29 : 1; + uint64_t pmc_lfir_mask_30 : 1; + uint64_t pmc_lfir_mask_31 : 1; + uint64_t pmc_lfir_mask_32 : 1; + uint64_t pmc_lfir_mask_33 : 1; + uint64_t pmc_lfir_mask_34 : 1; + uint64_t pmc_lfir_mask_35 : 1; + uint64_t pmc_lfir_mask_36 : 1; + uint64_t pmc_lfir_mask1_37_46 : 10; + uint64_t pmc_lfir_mask1_47 : 1; + uint64_t pmc_lfir_mask1_48 : 1; + uint64_t _reserved0 : 15; +#else + uint64_t _reserved0 : 15; + uint64_t pmc_lfir_mask1_48 : 1; + uint64_t pmc_lfir_mask1_47 : 1; + uint64_t pmc_lfir_mask1_37_46 : 10; + uint64_t pmc_lfir_mask_36 : 1; + uint64_t pmc_lfir_mask_35 : 1; + uint64_t pmc_lfir_mask_34 : 1; + uint64_t pmc_lfir_mask_33 : 1; + uint64_t pmc_lfir_mask_32 : 1; + uint64_t pmc_lfir_mask_31 : 1; + uint64_t pmc_lfir_mask_30 : 1; + uint64_t pmc_lfir_mask_29 : 1; + uint64_t pmc_lfir_mask_28 : 1; + uint64_t pmc_lfir_mask_27 : 1; + uint64_t pmc_lfir_mask_26 : 1; + uint64_t pmc_lfir_mask_25 : 1; + uint64_t pmc_lfir_mask_24 : 1; + uint64_t pmc_lfir_mask_23 : 1; + uint64_t pmc_lfir_mask_22 : 1; + uint64_t pmc_lfir_mask_21 : 1; + uint64_t pmc_lfir_mask_20 : 1; + uint64_t pmc_lfir_mask_19 : 1; + uint64_t pmc_lfir_mask_18 : 1; + uint64_t pmc_lfir_mask_17 : 1; + uint64_t pmc_lfir_mask_16 : 1; + uint64_t pmc_lfir_mask_15 : 1; + uint64_t pmc_lfir_mask_14 : 1; + uint64_t pmc_lfir_mask_13 : 1; + uint64_t pmc_lfir_mask_12 : 1; + uint64_t pmc_lfir_mask_11 : 1; + uint64_t pmc_lfir_mask_10 : 1; + uint64_t pmc_lfir_mask_9 : 1; + uint64_t pmc_lfir_mask_8 : 1; + uint64_t pmc_lfir_mask_7 : 1; + uint64_t pmc_lfir_mask_6 : 1; + uint64_t pmc_lfir_mask_5 : 1; + uint64_t pmc_lfir_mask_4 : 1; + uint64_t pmc_lfir_mask_3 : 1; + uint64_t pmc_lfir_mask_2 : 1; + uint64_t pmc_lfir_mask_1 : 1; + uint64_t pmc_lfir_mask_0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_lfir_err_mask_reg_t; + + + +typedef union pmc_lfir_err_mask_reg_and { + + 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 pmc_lfir_mask_0 : 1; + uint64_t pmc_lfir_mask_1 : 1; + uint64_t pmc_lfir_mask_2 : 1; + uint64_t pmc_lfir_mask_3 : 1; + uint64_t pmc_lfir_mask_4 : 1; + uint64_t pmc_lfir_mask_5 : 1; + uint64_t pmc_lfir_mask_6 : 1; + uint64_t pmc_lfir_mask_7 : 1; + uint64_t pmc_lfir_mask_8 : 1; + uint64_t pmc_lfir_mask_9 : 1; + uint64_t pmc_lfir_mask_10 : 1; + uint64_t pmc_lfir_mask_11 : 1; + uint64_t pmc_lfir_mask_12 : 1; + uint64_t pmc_lfir_mask_13 : 1; + uint64_t pmc_lfir_mask_14 : 1; + uint64_t pmc_lfir_mask_15 : 1; + uint64_t pmc_lfir_mask_16 : 1; + uint64_t pmc_lfir_mask_17 : 1; + uint64_t pmc_lfir_mask_18 : 1; + uint64_t pmc_lfir_mask_19 : 1; + uint64_t pmc_lfir_mask_20 : 1; + uint64_t pmc_lfir_mask_21 : 1; + uint64_t pmc_lfir_mask_22 : 1; + uint64_t pmc_lfir_mask_23 : 1; + uint64_t pmc_lfir_mask_24 : 1; + uint64_t pmc_lfir_mask_25 : 1; + uint64_t pmc_lfir_mask_26 : 1; + uint64_t pmc_lfir_mask_27 : 1; + uint64_t pmc_lfir_mask_28 : 1; + uint64_t pmc_lfir_mask_29 : 1; + uint64_t pmc_lfir_mask_30 : 1; + uint64_t pmc_lfir_mask_31 : 1; + uint64_t pmc_lfir_mask_32 : 1; + uint64_t pmc_lfir_mask_33 : 1; + uint64_t pmc_lfir_mask_34 : 1; + uint64_t pmc_lfir_mask_35 : 1; + uint64_t pmc_lfir_mask_36 : 1; + uint64_t pmc_lfir_mask1_37_46 : 10; + uint64_t pmc_lfir_mask1_47 : 1; + uint64_t pmc_lfir_mask1_48 : 1; + uint64_t _reserved0 : 15; +#else + uint64_t _reserved0 : 15; + uint64_t pmc_lfir_mask1_48 : 1; + uint64_t pmc_lfir_mask1_47 : 1; + uint64_t pmc_lfir_mask1_37_46 : 10; + uint64_t pmc_lfir_mask_36 : 1; + uint64_t pmc_lfir_mask_35 : 1; + uint64_t pmc_lfir_mask_34 : 1; + uint64_t pmc_lfir_mask_33 : 1; + uint64_t pmc_lfir_mask_32 : 1; + uint64_t pmc_lfir_mask_31 : 1; + uint64_t pmc_lfir_mask_30 : 1; + uint64_t pmc_lfir_mask_29 : 1; + uint64_t pmc_lfir_mask_28 : 1; + uint64_t pmc_lfir_mask_27 : 1; + uint64_t pmc_lfir_mask_26 : 1; + uint64_t pmc_lfir_mask_25 : 1; + uint64_t pmc_lfir_mask_24 : 1; + uint64_t pmc_lfir_mask_23 : 1; + uint64_t pmc_lfir_mask_22 : 1; + uint64_t pmc_lfir_mask_21 : 1; + uint64_t pmc_lfir_mask_20 : 1; + uint64_t pmc_lfir_mask_19 : 1; + uint64_t pmc_lfir_mask_18 : 1; + uint64_t pmc_lfir_mask_17 : 1; + uint64_t pmc_lfir_mask_16 : 1; + uint64_t pmc_lfir_mask_15 : 1; + uint64_t pmc_lfir_mask_14 : 1; + uint64_t pmc_lfir_mask_13 : 1; + uint64_t pmc_lfir_mask_12 : 1; + uint64_t pmc_lfir_mask_11 : 1; + uint64_t pmc_lfir_mask_10 : 1; + uint64_t pmc_lfir_mask_9 : 1; + uint64_t pmc_lfir_mask_8 : 1; + uint64_t pmc_lfir_mask_7 : 1; + uint64_t pmc_lfir_mask_6 : 1; + uint64_t pmc_lfir_mask_5 : 1; + uint64_t pmc_lfir_mask_4 : 1; + uint64_t pmc_lfir_mask_3 : 1; + uint64_t pmc_lfir_mask_2 : 1; + uint64_t pmc_lfir_mask_1 : 1; + uint64_t pmc_lfir_mask_0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_lfir_err_mask_reg_and_t; + + + +typedef union pmc_lfir_err_mask_reg_or { + + 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 pmc_lfir_mask_0 : 1; + uint64_t pmc_lfir_mask_1 : 1; + uint64_t pmc_lfir_mask_2 : 1; + uint64_t pmc_lfir_mask_3 : 1; + uint64_t pmc_lfir_mask_4 : 1; + uint64_t pmc_lfir_mask_5 : 1; + uint64_t pmc_lfir_mask_6 : 1; + uint64_t pmc_lfir_mask_7 : 1; + uint64_t pmc_lfir_mask_8 : 1; + uint64_t pmc_lfir_mask_9 : 1; + uint64_t pmc_lfir_mask_10 : 1; + uint64_t pmc_lfir_mask_11 : 1; + uint64_t pmc_lfir_mask_12 : 1; + uint64_t pmc_lfir_mask_13 : 1; + uint64_t pmc_lfir_mask_14 : 1; + uint64_t pmc_lfir_mask_15 : 1; + uint64_t pmc_lfir_mask_16 : 1; + uint64_t pmc_lfir_mask_17 : 1; + uint64_t pmc_lfir_mask_18 : 1; + uint64_t pmc_lfir_mask_19 : 1; + uint64_t pmc_lfir_mask_20 : 1; + uint64_t pmc_lfir_mask_21 : 1; + uint64_t pmc_lfir_mask_22 : 1; + uint64_t pmc_lfir_mask_23 : 1; + uint64_t pmc_lfir_mask_24 : 1; + uint64_t pmc_lfir_mask_25 : 1; + uint64_t pmc_lfir_mask_26 : 1; + uint64_t pmc_lfir_mask_27 : 1; + uint64_t pmc_lfir_mask_28 : 1; + uint64_t pmc_lfir_mask_29 : 1; + uint64_t pmc_lfir_mask_30 : 1; + uint64_t pmc_lfir_mask_31 : 1; + uint64_t pmc_lfir_mask_32 : 1; + uint64_t pmc_lfir_mask_33 : 1; + uint64_t pmc_lfir_mask_34 : 1; + uint64_t pmc_lfir_mask_35 : 1; + uint64_t pmc_lfir_mask_36 : 1; + uint64_t pmc_lfir_mask1_37_46 : 10; + uint64_t pmc_lfir_mask1_47 : 1; + uint64_t pmc_lfir_mask1_48 : 1; + uint64_t _reserved0 : 15; +#else + uint64_t _reserved0 : 15; + uint64_t pmc_lfir_mask1_48 : 1; + uint64_t pmc_lfir_mask1_47 : 1; + uint64_t pmc_lfir_mask1_37_46 : 10; + uint64_t pmc_lfir_mask_36 : 1; + uint64_t pmc_lfir_mask_35 : 1; + uint64_t pmc_lfir_mask_34 : 1; + uint64_t pmc_lfir_mask_33 : 1; + uint64_t pmc_lfir_mask_32 : 1; + uint64_t pmc_lfir_mask_31 : 1; + uint64_t pmc_lfir_mask_30 : 1; + uint64_t pmc_lfir_mask_29 : 1; + uint64_t pmc_lfir_mask_28 : 1; + uint64_t pmc_lfir_mask_27 : 1; + uint64_t pmc_lfir_mask_26 : 1; + uint64_t pmc_lfir_mask_25 : 1; + uint64_t pmc_lfir_mask_24 : 1; + uint64_t pmc_lfir_mask_23 : 1; + uint64_t pmc_lfir_mask_22 : 1; + uint64_t pmc_lfir_mask_21 : 1; + uint64_t pmc_lfir_mask_20 : 1; + uint64_t pmc_lfir_mask_19 : 1; + uint64_t pmc_lfir_mask_18 : 1; + uint64_t pmc_lfir_mask_17 : 1; + uint64_t pmc_lfir_mask_16 : 1; + uint64_t pmc_lfir_mask_15 : 1; + uint64_t pmc_lfir_mask_14 : 1; + uint64_t pmc_lfir_mask_13 : 1; + uint64_t pmc_lfir_mask_12 : 1; + uint64_t pmc_lfir_mask_11 : 1; + uint64_t pmc_lfir_mask_10 : 1; + uint64_t pmc_lfir_mask_9 : 1; + uint64_t pmc_lfir_mask_8 : 1; + uint64_t pmc_lfir_mask_7 : 1; + uint64_t pmc_lfir_mask_6 : 1; + uint64_t pmc_lfir_mask_5 : 1; + uint64_t pmc_lfir_mask_4 : 1; + uint64_t pmc_lfir_mask_3 : 1; + uint64_t pmc_lfir_mask_2 : 1; + uint64_t pmc_lfir_mask_1 : 1; + uint64_t pmc_lfir_mask_0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_lfir_err_mask_reg_or_t; + + + +typedef union pmc_lfir_action0_reg { + + 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 pmc_lfir_action0_0 : 1; + uint64_t pmc_lfir_action0_1 : 1; + uint64_t pmc_lfir_action0_2 : 1; + uint64_t pmc_lfir_action0_3 : 1; + uint64_t pmc_lfir_action0_4 : 1; + uint64_t pmc_lfir_action0_5 : 1; + uint64_t pmc_lfir_action0_6 : 1; + uint64_t pmc_lfir_action0_7 : 1; + uint64_t pmc_lfir_action0_8 : 1; + uint64_t pmc_lfir_action0_9 : 1; + uint64_t pmc_lfir_action0_10 : 1; + uint64_t pmc_lfir_action0_11 : 1; + uint64_t pmc_lfir_action0_12 : 1; + uint64_t pmc_lfir_action0_13 : 1; + uint64_t pmc_lfir_action0_14 : 1; + uint64_t pmc_lfir_action0_15 : 1; + uint64_t pmc_lfir_action0_16 : 1; + uint64_t pmc_lfir_action0_17 : 1; + uint64_t pmc_lfir_action0_18 : 1; + uint64_t pmc_lfir_action0_19 : 1; + uint64_t pmc_lfir_action0_20 : 1; + uint64_t pmc_lfir_action0_21 : 1; + uint64_t pmc_lfir_action0_22 : 1; + uint64_t pmc_lfir_action0_23 : 1; + uint64_t pmc_lfir_action0_24 : 1; + uint64_t pmc_lfir_action0_25 : 1; + uint64_t pmc_lfir_action0_26 : 1; + uint64_t pmc_lfir_action0_27 : 1; + uint64_t pmc_lfir_action0_28 : 1; + uint64_t pmc_lfir_action0_29 : 1; + uint64_t pmc_lfir_action0_30 : 1; + uint64_t pmc_lfir_action0_31 : 1; + uint64_t pmc_lfir_action0_32 : 1; + uint64_t pmc_lfir_action0_33 : 1; + uint64_t pmc_lfir_action0_34 : 1; + uint64_t pmc_lfir_action0_35 : 1; + uint64_t pmc_lfir_action0_36 : 1; + uint64_t pmc_lfir_action0_37_46 : 10; + uint64_t pmc_lfir_action0_47 : 1; + uint64_t pmc_lfir_action0_48 : 1; + uint64_t _reserved0 : 15; +#else + uint64_t _reserved0 : 15; + uint64_t pmc_lfir_action0_48 : 1; + uint64_t pmc_lfir_action0_47 : 1; + uint64_t pmc_lfir_action0_37_46 : 10; + uint64_t pmc_lfir_action0_36 : 1; + uint64_t pmc_lfir_action0_35 : 1; + uint64_t pmc_lfir_action0_34 : 1; + uint64_t pmc_lfir_action0_33 : 1; + uint64_t pmc_lfir_action0_32 : 1; + uint64_t pmc_lfir_action0_31 : 1; + uint64_t pmc_lfir_action0_30 : 1; + uint64_t pmc_lfir_action0_29 : 1; + uint64_t pmc_lfir_action0_28 : 1; + uint64_t pmc_lfir_action0_27 : 1; + uint64_t pmc_lfir_action0_26 : 1; + uint64_t pmc_lfir_action0_25 : 1; + uint64_t pmc_lfir_action0_24 : 1; + uint64_t pmc_lfir_action0_23 : 1; + uint64_t pmc_lfir_action0_22 : 1; + uint64_t pmc_lfir_action0_21 : 1; + uint64_t pmc_lfir_action0_20 : 1; + uint64_t pmc_lfir_action0_19 : 1; + uint64_t pmc_lfir_action0_18 : 1; + uint64_t pmc_lfir_action0_17 : 1; + uint64_t pmc_lfir_action0_16 : 1; + uint64_t pmc_lfir_action0_15 : 1; + uint64_t pmc_lfir_action0_14 : 1; + uint64_t pmc_lfir_action0_13 : 1; + uint64_t pmc_lfir_action0_12 : 1; + uint64_t pmc_lfir_action0_11 : 1; + uint64_t pmc_lfir_action0_10 : 1; + uint64_t pmc_lfir_action0_9 : 1; + uint64_t pmc_lfir_action0_8 : 1; + uint64_t pmc_lfir_action0_7 : 1; + uint64_t pmc_lfir_action0_6 : 1; + uint64_t pmc_lfir_action0_5 : 1; + uint64_t pmc_lfir_action0_4 : 1; + uint64_t pmc_lfir_action0_3 : 1; + uint64_t pmc_lfir_action0_2 : 1; + uint64_t pmc_lfir_action0_1 : 1; + uint64_t pmc_lfir_action0_0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_lfir_action0_reg_t; + + + +typedef union pmc_lfir_action1_reg { + + 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 pmc_lfir_action1_0 : 1; + uint64_t pmc_lfir_action1_1 : 1; + uint64_t pmc_lfir_action1_2 : 1; + uint64_t pmc_lfir_action1_3 : 1; + uint64_t pmc_lfir_action1_4 : 1; + uint64_t pmc_lfir_action1_5 : 1; + uint64_t pmc_lfir_action1_6 : 1; + uint64_t pmc_lfir_action1_7 : 1; + uint64_t pmc_lfir_action1_8 : 1; + uint64_t pmc_lfir_action1_9 : 1; + uint64_t pmc_lfir_action1_10 : 1; + uint64_t pmc_lfir_action1_11 : 1; + uint64_t pmc_lfir_action1_12 : 1; + uint64_t pmc_lfir_action1_13 : 1; + uint64_t pmc_lfir_action1_14 : 1; + uint64_t pmc_lfir_action1_15 : 1; + uint64_t pmc_lfir_action1_16 : 1; + uint64_t pmc_lfir_action1_17 : 1; + uint64_t pmc_lfir_action1_18 : 1; + uint64_t pmc_lfir_action1_19 : 1; + uint64_t pmc_lfir_action1_20 : 1; + uint64_t pmc_lfir_action1_21 : 1; + uint64_t pmc_lfir_action1_22 : 1; + uint64_t pmc_lfir_action1_23 : 1; + uint64_t pmc_lfir_action1_24 : 1; + uint64_t pmc_lfir_action1_25 : 1; + uint64_t pmc_lfir_action1_26 : 1; + uint64_t pmc_lfir_action1_27 : 1; + uint64_t pmc_lfir_action1_28 : 1; + uint64_t pmc_lfir_action1_29 : 1; + uint64_t pmc_lfir_action1_30 : 1; + uint64_t pmc_lfir_action1_31 : 1; + uint64_t pmc_lfir_action1_32 : 1; + uint64_t pmc_lfir_action1_33 : 1; + uint64_t pmc_lfir_action1_34 : 1; + uint64_t pmc_lfir_action1_35 : 1; + uint64_t pmc_lfir_action1_36 : 1; + uint64_t pmc_lfir_action1_37_46 : 10; + uint64_t pmc_lfir_action1_47 : 1; + uint64_t pmc_lfir_action1_48 : 1; + uint64_t _reserved0 : 15; +#else + uint64_t _reserved0 : 15; + uint64_t pmc_lfir_action1_48 : 1; + uint64_t pmc_lfir_action1_47 : 1; + uint64_t pmc_lfir_action1_37_46 : 10; + uint64_t pmc_lfir_action1_36 : 1; + uint64_t pmc_lfir_action1_35 : 1; + uint64_t pmc_lfir_action1_34 : 1; + uint64_t pmc_lfir_action1_33 : 1; + uint64_t pmc_lfir_action1_32 : 1; + uint64_t pmc_lfir_action1_31 : 1; + uint64_t pmc_lfir_action1_30 : 1; + uint64_t pmc_lfir_action1_29 : 1; + uint64_t pmc_lfir_action1_28 : 1; + uint64_t pmc_lfir_action1_27 : 1; + uint64_t pmc_lfir_action1_26 : 1; + uint64_t pmc_lfir_action1_25 : 1; + uint64_t pmc_lfir_action1_24 : 1; + uint64_t pmc_lfir_action1_23 : 1; + uint64_t pmc_lfir_action1_22 : 1; + uint64_t pmc_lfir_action1_21 : 1; + uint64_t pmc_lfir_action1_20 : 1; + uint64_t pmc_lfir_action1_19 : 1; + uint64_t pmc_lfir_action1_18 : 1; + uint64_t pmc_lfir_action1_17 : 1; + uint64_t pmc_lfir_action1_16 : 1; + uint64_t pmc_lfir_action1_15 : 1; + uint64_t pmc_lfir_action1_14 : 1; + uint64_t pmc_lfir_action1_13 : 1; + uint64_t pmc_lfir_action1_12 : 1; + uint64_t pmc_lfir_action1_11 : 1; + uint64_t pmc_lfir_action1_10 : 1; + uint64_t pmc_lfir_action1_9 : 1; + uint64_t pmc_lfir_action1_8 : 1; + uint64_t pmc_lfir_action1_7 : 1; + uint64_t pmc_lfir_action1_6 : 1; + uint64_t pmc_lfir_action1_5 : 1; + uint64_t pmc_lfir_action1_4 : 1; + uint64_t pmc_lfir_action1_3 : 1; + uint64_t pmc_lfir_action1_2 : 1; + uint64_t pmc_lfir_action1_1 : 1; + uint64_t pmc_lfir_action1_0 : 1; +#endif // _BIG_ENDIAN + } fields; +} pmc_lfir_action1_reg_t; + + + +typedef union pmc_lfir_wof_reg { + + 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 pmc_lfir_wof : 49; + uint64_t _reserved0 : 15; +#else + uint64_t _reserved0 : 15; + uint64_t pmc_lfir_wof : 49; +#endif // _BIG_ENDIAN + } fields; +} pmc_lfir_wof_reg_t; + + +#endif // __ASSEMBLER__ +#endif // __PMC_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/pmc_register_addresses.h b/src/ssx/pgp/registers/pmc_register_addresses.h new file mode 100755 index 0000000..96f8dac --- /dev/null +++ b/src/ssx/pgp/registers/pmc_register_addresses.h @@ -0,0 +1,116 @@ +#ifndef __PMC_REGISTER_ADDRESSES_H__ +#define __PMC_REGISTER_ADDRESSES_H__ + +// $Id: pmc_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pmc_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pmc_register_addresses.h +/// \brief Symbolic addresses for the PMC unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define PMC_OCI_BASE 0x40010000 +#define PMC_MODE_REG 0x40010000 +#define PMC_HARDWARE_AUCTION_PSTATE_REG 0x40010008 +#define PMC_PSTATE_MONITOR_AND_CTRL_REG 0x40010010 +#define PMC_RAIL_BOUNDS_REGISTER 0x40010018 +#define PMC_GLOBAL_PSTATE_BOUNDS_REG 0x40010020 +#define PMC_PARAMETER_REG0 0x40010028 +#define PMC_PARAMETER_REG1 0x40010030 +#define PMC_EFF_GLOBAL_ACTUAL_VOLTAGE_REG 0x40010038 +#define PMC_GLOBAL_ACTUAL_VOLTAGE_REG 0x40010040 +#define PMC_STATUS_REG 0x40010048 +#define PMC_PHASE_ENABLE_REG 0x40010050 +#define PMC_UNDERVOLTING_REG 0x40010060 +#define PMC_CORE_DECONFIGURATION_REG 0x40010068 +#define PMC_INTCHP_CTRL_REG1 0x40010080 +#define PMC_INTCHP_CTRL_REG2 0x40010088 +#define PMC_INTCHP_CTRL_REG4 0x40010090 +#define PMC_INTCHP_STATUS_REG 0x40010098 +#define PMC_INTCHP_COMMAND_REG 0x400100a0 +#define PMC_INTCHP_MSG_WDATA 0x400100a8 +#define PMC_INTCHP_MSG_RDATA 0x400100b0 +#define PMC_INTCHP_PSTATE_REG 0x400100b8 +#define PMC_INTCHP_GLOBACK_REG 0x400100c0 +#define PMC_FSMSTATE_STATUS_REG 0x40010100 +#define PMC_TRACE_MODE_REG 0x40010180 +#define PMC_SPIV_CTRL_REG0A 0x40010200 +#define PMC_SPIV_CTRL_REG0B 0x40010208 +#define PMC_SPIV_CTRL_REG1 0x40010210 +#define PMC_SPIV_CTRL_REG2 0x40010218 +#define PMC_SPIV_CTRL_REG3 0x40010220 +#define PMC_SPIV_CTRL_REG4 0x40010228 +#define PMC_SPIV_STATUS_REG 0x40010230 +#define PMC_SPIV_COMMAND_REG 0x40010238 +#define PMC_O2S_CTRL_REG0A 0x40010280 +#define PMC_O2S_CTRL_REG0B 0x40010288 +#define PMC_O2S_CTRL_REG1 0x40010290 +#define PMC_O2S_CTRL_REG2 0x40010298 +#define PMC_O2S_CTRL_REG4 0x400102a8 +#define PMC_O2S_STATUS_REG 0x400102b0 +#define PMC_O2S_COMMAND_REG 0x400102b8 +#define PMC_O2S_WDATA_REG 0x400102c0 +#define PMC_O2S_RDATA_REG 0x400102c8 +#define PMC_O2P_ADDR_REG 0x40010300 +#define PMC_O2P_CTRL_STATUS_REG 0x40010308 +#define PMC_O2P_SEND_DATA_HI_REG 0x40010310 +#define PMC_O2P_SEND_DATA_LO_REG 0x40010318 +#define PMC_O2P_RECV_DATA_HI_REG 0x40010320 +#define PMC_O2P_RECV_DATA_LO_REG 0x40010328 +#define PMC_OCC_HEARTBEAT_REG 0x40010330 +#define PMC_ERROR_INT_MASK_HI_REG 0x40010338 +#define PMC_ERROR_INT_MASK_LO_REG 0x40010340 +#define PMC_IDLE_SUSPEND_MASK_REG 0x40010348 +#define PMC_PEND_IDLE_REQ_REG0 0x40010400 +#define PMC_PEND_IDLE_REQ_REG1 0x40010408 +#define PMC_PEND_IDLE_REQ_REG2 0x40010410 +#define PMC_PEND_IDLE_REQ_REG3 0x40010418 +#define PMC_SLEEP_INT_REQ_VEC_REG0 0x40010420 +#define PMC_SLEEP_INT_REQ_VEC_REG1 0x40010428 +#define PMC_SLEEP_INT_REQ_VEC_REG2 0x40010430 +#define PMC_SLEEP_INT_REQ_VEC_REG3 0x40010438 +#define PMC_WINKLE_INT_REQ_VEC_REG0 0x40010440 +#define PMC_WINKLE_INT_REQ_VEC_REG1 0x40010448 +#define PMC_WINKLE_INT_REQ_VEC_REG2 0x40010450 +#define PMC_WINKLE_INT_REQ_VEC_REG3 0x40010458 +#define PMC_NAP_INT_REQ_VEC_REG0 0x40010460 +#define PMC_NAP_INT_REQ_VEC_REG1 0x40010468 +#define PMC_PORE_REQ_REG0 0x40010470 +#define PMC_PORE_REQ_REG1 0x40010478 +#define PMC_PORE_REQ_STAT_REG 0x40010480 +#define PMC_PORE_REQ_TOUT_TH_REG 0x40010488 +#define PMC_DEEP_EXIT_MASK_REG 0x40010490 +#define PMC_DEEP_EXIT_MASK_REG_AND 0x40010500 +#define PMC_DEEP_EXIT_MASK_REG_OR 0x40010508 +#define PMC_CORE_PSTATE_REG0 0x400104a0 +#define PMC_CORE_PSTATE_REG1 0x400104a8 +#define PMC_CORE_PSTATE_REG2 0x400104b0 +#define PMC_CORE_PSTATE_REG3 0x400104b8 +#define PMC_CORE_POWER_DONATION_REG 0x400104c0 +#define PMC_PMAX_SYNC_COLLECTION_REG 0x400104c8 +#define PMC_PMAX_SYNC_COLLECTION_MASK_REG 0x400104d0 +#define PMC_GPSA_ACK_COLLECTION_REG 0x400104d8 +#define PMC_GPSA_ACK_COLLECTION_MASK_REG 0x400104e0 +#define PMC_PORE_SCRATCH_REG0 0x400104e8 +#define PMC_PORE_SCRATCH_REG1 0x400104f0 +#define PMC_DEEP_IDLE_EXIT_REG 0x400104f8 +#define PMC_DEEP_STATUS_REG 0x40010510 +#define PMC_PIB_BASE 0x01010840 +#define PMC_LFIR_ERR_REG 0x01010840 +#define PMC_LFIR_ERR_REG_AND 0x01010841 +#define PMC_LFIR_ERR_REG_OR 0x01010842 +#define PMC_LFIR_ERR_MASK_REG 0x01010843 +#define PMC_LFIR_ERR_MASK_REG_AND 0x01010844 +#define PMC_LFIR_ERR_MASK_REG_OR 0x01010845 +#define PMC_LFIR_ACTION0_REG 0x01010846 +#define PMC_LFIR_ACTION1_REG 0x01010847 +#define PMC_LFIR_WOF_REG 0x01010848 + +#endif // __PMC_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/pore_firmware_registers.h b/src/ssx/pgp/registers/pore_firmware_registers.h new file mode 100755 index 0000000..76127d9 --- /dev/null +++ b/src/ssx/pgp/registers/pore_firmware_registers.h @@ -0,0 +1,906 @@ +#ifndef __PORE_FIRMWARE_REGISTERS_H__ +#define __PORE_FIRMWARE_REGISTERS_H__ + +// $Id: pore_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pore_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pore_firmware_registers.h +/// \brief C register structs for the PORE unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union pore_status { + + 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 cur_state : 8; + uint64_t freeze_action : 1; + uint64_t interrupt_pending : 1; + uint64_t spare : 2; + uint64_t stack_pointer : 4; + uint64_t pc : 48; +#else + uint64_t pc : 48; + uint64_t stack_pointer : 4; + uint64_t spare : 2; + uint64_t interrupt_pending : 1; + uint64_t freeze_action : 1; + uint64_t cur_state : 8; +#endif // _BIG_ENDIAN + } fields; +} pore_status_t; + +#endif // __ASSEMBLER__ +#define PORE_STATUS_CUR_STATE_MASK SIXTYFOUR_BIT_CONSTANT(0xff00000000000000) +#define PORE_STATUS_FREEZE_ACTION SIXTYFOUR_BIT_CONSTANT(0x0080000000000000) +#define PORE_STATUS_INTERRUPT_PENDING SIXTYFOUR_BIT_CONSTANT(0x0040000000000000) +#define PORE_STATUS_SPARE_MASK SIXTYFOUR_BIT_CONSTANT(0x0030000000000000) +#define PORE_STATUS_STACK_POINTER_MASK SIXTYFOUR_BIT_CONSTANT(0x000f000000000000) +#define PORE_STATUS_PC_MASK SIXTYFOUR_BIT_CONSTANT(0xffffffffffffffff) +#ifndef __ASSEMBLER__ + + +typedef union pore_control { + + 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 start_stop : 1; + uint64_t continue_step : 1; + uint64_t skip : 1; + uint64_t set_pc : 1; + uint64_t set_tp_scan_clk : 3; + uint64_t lock_exe_trig : 1; + uint64_t freeze_mask : 1; + uint64_t check_parity : 1; + uint64_t prv_parity : 1; + uint64_t trap_enable : 1; + uint64_t narrow_mode_trace : 1; + uint64_t interruptible : 1; + uint64_t pore_done_override : 1; + uint64_t interruptible_en : 1; + uint64_t pc_brk_pt : 48; +#else + uint64_t pc_brk_pt : 48; + uint64_t interruptible_en : 1; + uint64_t pore_done_override : 1; + uint64_t interruptible : 1; + uint64_t narrow_mode_trace : 1; + 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 // _BIG_ENDIAN + } fields; +} pore_control_t; + +#endif // __ASSEMBLER__ +#define PORE_CONTROL_START_STOP SIXTYFOUR_BIT_CONSTANT(0x8000000000000000) +#define PORE_CONTROL_CONTINUE_STEP SIXTYFOUR_BIT_CONSTANT(0x4000000000000000) +#define PORE_CONTROL_SKIP SIXTYFOUR_BIT_CONSTANT(0x2000000000000000) +#define PORE_CONTROL_SET_PC SIXTYFOUR_BIT_CONSTANT(0x1000000000000000) +#define PORE_CONTROL_SET_TP_SCAN_CLK_MASK SIXTYFOUR_BIT_CONSTANT(0x0e00000000000000) +#define PORE_CONTROL_LOCK_EXE_TRIG SIXTYFOUR_BIT_CONSTANT(0x0100000000000000) +#define PORE_CONTROL_FREEZE_MASK SIXTYFOUR_BIT_CONSTANT(0x0080000000000000) +#define PORE_CONTROL_CHECK_PARITY SIXTYFOUR_BIT_CONSTANT(0x0040000000000000) +#define PORE_CONTROL_PRV_PARITY SIXTYFOUR_BIT_CONSTANT(0x0020000000000000) +#define PORE_CONTROL_TRAP_ENABLE SIXTYFOUR_BIT_CONSTANT(0x0010000000000000) +#define PORE_CONTROL_NARROW_MODE_TRACE SIXTYFOUR_BIT_CONSTANT(0x0008000000000000) +#define PORE_CONTROL_INTERRUPTIBLE SIXTYFOUR_BIT_CONSTANT(0x0004000000000000) +#define PORE_CONTROL_PORE_DONE_OVERRIDE SIXTYFOUR_BIT_CONSTANT(0x0002000000000000) +#define PORE_CONTROL_INTERRUPTIBLE_EN SIXTYFOUR_BIT_CONSTANT(0x0001000000000000) +#define PORE_CONTROL_PC_BRK_PT_MASK SIXTYFOUR_BIT_CONSTANT(0xffffffffffffffff) +#ifndef __ASSEMBLER__ + + +typedef union pore_reset { + + 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 fn_reset : 1; + uint64_t oci_reset : 1; + uint64_t _reserved0 : 62; +#else + uint64_t _reserved0 : 62; + uint64_t oci_reset : 1; + uint64_t fn_reset : 1; +#endif // _BIG_ENDIAN + } fields; +} pore_reset_t; + + + +typedef union pore_error_mask { + + 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 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_err_output0 : 1; + uint64_t enable_fatal_err_output1 : 1; + uint64_t enable_fatal_err_output2 : 1; + uint64_t enable_fatal_err_output3 : 1; + uint64_t enable_fatal_err_output4 : 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 i2c_bad_status_0 : 1; + uint64_t i2c_bad_status_1 : 1; + uint64_t i2c_bad_status_2 : 1; + uint64_t i2c_bad_status_3 : 1; + uint64_t group_parity_error_0 : 1; + uint64_t group_parity_error_1 : 1; + uint64_t group_parity_error_2 : 1; + uint64_t group_parity_error_3 : 1; + uint64_t group_parity_error_4 : 1; + uint64_t _reserved0 : 34; +#else + uint64_t _reserved0 : 34; + uint64_t group_parity_error_4 : 1; + uint64_t group_parity_error_3 : 1; + uint64_t group_parity_error_2 : 1; + uint64_t group_parity_error_1 : 1; + uint64_t group_parity_error_0 : 1; + uint64_t i2c_bad_status_3 : 1; + uint64_t i2c_bad_status_2 : 1; + uint64_t i2c_bad_status_1 : 1; + uint64_t i2c_bad_status_0 : 1; + 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_err_output4 : 1; + uint64_t enable_fatal_err_output3 : 1; + uint64_t enable_fatal_err_output2 : 1; + uint64_t enable_fatal_err_output1 : 1; + uint64_t enable_fatal_err_output0 : 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 // _BIG_ENDIAN + } fields; +} pore_error_mask_t; + +#endif // __ASSEMBLER__ +#define PORE_ERROR_MASK_ENABLE_ERR_HANDLER0 SIXTYFOUR_BIT_CONSTANT(0x8000000000000000) +#define PORE_ERROR_MASK_ENABLE_ERR_HANDLER1 SIXTYFOUR_BIT_CONSTANT(0x4000000000000000) +#define PORE_ERROR_MASK_ENABLE_ERR_HANDLER2 SIXTYFOUR_BIT_CONSTANT(0x2000000000000000) +#define PORE_ERROR_MASK_ENABLE_ERR_HANDLER3 SIXTYFOUR_BIT_CONSTANT(0x1000000000000000) +#define PORE_ERROR_MASK_ENABLE_ERR_HANDLER4 SIXTYFOUR_BIT_CONSTANT(0x0800000000000000) +#define PORE_ERROR_MASK_ENABLE_ERR_OUTPUT0 SIXTYFOUR_BIT_CONSTANT(0x0400000000000000) +#define PORE_ERROR_MASK_ENABLE_ERR_OUTPUT1 SIXTYFOUR_BIT_CONSTANT(0x0200000000000000) +#define PORE_ERROR_MASK_ENABLE_ERR_OUTPUT2 SIXTYFOUR_BIT_CONSTANT(0x0100000000000000) +#define PORE_ERROR_MASK_ENABLE_ERR_OUTPUT3 SIXTYFOUR_BIT_CONSTANT(0x0080000000000000) +#define PORE_ERROR_MASK_ENABLE_ERR_OUTPUT4 SIXTYFOUR_BIT_CONSTANT(0x0040000000000000) +#define PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT0 SIXTYFOUR_BIT_CONSTANT(0x0020000000000000) +#define PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT1 SIXTYFOUR_BIT_CONSTANT(0x0010000000000000) +#define PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT2 SIXTYFOUR_BIT_CONSTANT(0x0008000000000000) +#define PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT3 SIXTYFOUR_BIT_CONSTANT(0x0004000000000000) +#define PORE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT4 SIXTYFOUR_BIT_CONSTANT(0x0002000000000000) +#define PORE_ERROR_MASK_STOP_EXE_ON_ERROR0 SIXTYFOUR_BIT_CONSTANT(0x0001000000000000) +#define PORE_ERROR_MASK_STOP_EXE_ON_ERROR1 SIXTYFOUR_BIT_CONSTANT(0x0000800000000000) +#define PORE_ERROR_MASK_STOP_EXE_ON_ERROR2 SIXTYFOUR_BIT_CONSTANT(0x0000400000000000) +#define PORE_ERROR_MASK_STOP_EXE_ON_ERROR3 SIXTYFOUR_BIT_CONSTANT(0x0000200000000000) +#define PORE_ERROR_MASK_STOP_EXE_ON_ERROR4 SIXTYFOUR_BIT_CONSTANT(0x0000100000000000) +#define PORE_ERROR_MASK_GATE_CHIPLET_OFFLINE_ERR SIXTYFOUR_BIT_CONSTANT(0x0000080000000000) +#define PORE_ERROR_MASK_I2C_BAD_STATUS_0 SIXTYFOUR_BIT_CONSTANT(0x0000040000000000) +#define PORE_ERROR_MASK_I2C_BAD_STATUS_1 SIXTYFOUR_BIT_CONSTANT(0x0000020000000000) +#define PORE_ERROR_MASK_I2C_BAD_STATUS_2 SIXTYFOUR_BIT_CONSTANT(0x0000010000000000) +#define PORE_ERROR_MASK_I2C_BAD_STATUS_3 SIXTYFOUR_BIT_CONSTANT(0x0000008000000000) +#define PORE_ERROR_MASK_GROUP_PARITY_ERROR_0 SIXTYFOUR_BIT_CONSTANT(0x0000004000000000) +#define PORE_ERROR_MASK_GROUP_PARITY_ERROR_1 SIXTYFOUR_BIT_CONSTANT(0x0000002000000000) +#define PORE_ERROR_MASK_GROUP_PARITY_ERROR_2 SIXTYFOUR_BIT_CONSTANT(0x0000001000000000) +#define PORE_ERROR_MASK_GROUP_PARITY_ERROR_3 SIXTYFOUR_BIT_CONSTANT(0x0000000800000000) +#define PORE_ERROR_MASK_GROUP_PARITY_ERROR_4 SIXTYFOUR_BIT_CONSTANT(0x0000000400000000) +#ifndef __ASSEMBLER__ + + +typedef union pore_prv_base_address0 { + + 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 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 // _BIG_ENDIAN + } fields; +} pore_prv_base_address0_t; + + + +typedef union pore_prv_base_address1 { + + 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 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 // _BIG_ENDIAN + } fields; +} pore_prv_base_address1_t; + + + +typedef union pore_oci_base_address0 { + + 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 spare : 18; + uint64_t oci_mem_route : 14; + uint64_t oci_base_address : 32; +#else + uint64_t oci_base_address : 32; + uint64_t oci_mem_route : 14; + uint64_t spare : 18; +#endif // _BIG_ENDIAN + } fields; +} pore_oci_base_address0_t; + + + +typedef union pore_oci_base_address1 { + + 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 spare : 18; + uint64_t oci_mem_route : 14; + uint64_t oci_base_address : 32; +#else + uint64_t oci_base_address : 32; + uint64_t oci_mem_route : 14; + uint64_t spare : 18; +#endif // _BIG_ENDIAN + } fields; +} pore_oci_base_address1_t; + + + +typedef union pore_table_base_addr { + + 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 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 // _BIG_ENDIAN + } fields; +} pore_table_base_addr_t; + + + +typedef union pore_exe_trigger { + + 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 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 // _BIG_ENDIAN + } fields; +} pore_exe_trigger_t; + + + +typedef union pore_scratch0 { + + 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 zeroes : 8; + uint64_t scratch0 : 24; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t scratch0 : 24; + uint64_t zeroes : 8; +#endif // _BIG_ENDIAN + } fields; +} pore_scratch0_t; + + + +typedef union pore_scratch1 { + + 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 scratch1 : 64; +#else + uint64_t scratch1 : 64; +#endif // _BIG_ENDIAN + } fields; +} pore_scratch1_t; + + + +typedef union pore_scratch2 { + + 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 scratch2 : 64; +#else + uint64_t scratch2 : 64; +#endif // _BIG_ENDIAN + } fields; +} pore_scratch2_t; + + + +typedef union pore_ibuf_01 { + + 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 ibuf0 : 32; + uint64_t ibuf1 : 32; +#else + uint64_t ibuf1 : 32; + uint64_t ibuf0 : 32; +#endif // _BIG_ENDIAN + } fields; +} pore_ibuf_01_t; + + + +typedef union pore_ibuf_2 { + + 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 ibuf2 : 32; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t ibuf2 : 32; +#endif // _BIG_ENDIAN + } fields; +} pore_ibuf_2_t; + + + +typedef union pore_dbg0 { + + 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 last_completed_address : 32; + uint64_t last_pib_parity_fail : 1; + uint64_t last_ret_code_prv : 3; + uint64_t i2c_bad_status0 : 1; + uint64_t i2c_bad_status1 : 1; + uint64_t i2c_bad_status2 : 1; + uint64_t i2c_bad_status3 : 1; + uint64_t group_parity_error0 : 1; + uint64_t group_parity_error1 : 1; + uint64_t group_parity_error2 : 1; + uint64_t group_parity_error3 : 1; + uint64_t group_parity_error4 : 1; + uint64_t interrupt_counter : 8; + uint64_t _reserved0 : 11; +#else + uint64_t _reserved0 : 11; + uint64_t interrupt_counter : 8; + uint64_t group_parity_error4 : 1; + uint64_t group_parity_error3 : 1; + uint64_t group_parity_error2 : 1; + uint64_t group_parity_error1 : 1; + uint64_t group_parity_error0 : 1; + uint64_t i2c_bad_status3 : 1; + uint64_t i2c_bad_status2 : 1; + uint64_t i2c_bad_status1 : 1; + uint64_t i2c_bad_status0 : 1; + uint64_t last_ret_code_prv : 3; + uint64_t last_pib_parity_fail : 1; + uint64_t last_completed_address : 32; +#endif // _BIG_ENDIAN + } fields; +} pore_dbg0_t; + + + +typedef union pore_dbg1 { + + 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 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 fast_i2c_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 fast_i2c_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 // _BIG_ENDIAN + } fields; +} pore_dbg1_t; + + + +typedef union pore_pc_stack0 { + + 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 pc_stack0 : 48; + uint64_t _reserved0 : 11; + uint64_t set_new_stack_pointer : 1; + uint64_t new_stack_pointer : 4; +#else + uint64_t new_stack_pointer : 4; + uint64_t set_new_stack_pointer : 1; + uint64_t _reserved0 : 11; + uint64_t pc_stack0 : 48; +#endif // _BIG_ENDIAN + } fields; +} pore_pc_stack0_t; + + + +typedef union pore_pc_stack1 { + + 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 pc_stack1 : 48; + uint64_t _reserved0 : 16; +#else + uint64_t _reserved0 : 16; + uint64_t pc_stack1 : 48; +#endif // _BIG_ENDIAN + } fields; +} pore_pc_stack1_t; + + + +typedef union pore_pc_stack2 { + + 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 pc_stack2 : 48; + uint64_t _reserved0 : 16; +#else + uint64_t _reserved0 : 16; + uint64_t pc_stack2 : 48; +#endif // _BIG_ENDIAN + } fields; +} pore_pc_stack2_t; + + + +typedef union pore_id_flags { + + 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 reserved0 : 32; + uint64_t pib_parity_fail : 1; + uint64_t pib_status : 3; + uint64_t oci_parity_fail : 1; + uint64_t oci_status : 3; + uint64_t reserved1 : 8; + uint64_t ugt : 1; + uint64_t ult : 1; + uint64_t sgt : 1; + uint64_t slt : 1; + uint64_t c : 1; + uint64_t o : 1; + uint64_t n : 1; + uint64_t z : 1; + uint64_t reserved2 : 4; + uint64_t ibuf_id : 4; +#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 // _BIG_ENDIAN + } fields; +} pore_id_flags_t; + + + +typedef union pore_data0 { + + 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 data0 : 32; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t data0 : 32; +#endif // _BIG_ENDIAN + } fields; +} pore_data0_t; + + + +typedef union pore_memory_reloc { + + 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 _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 // _BIG_ENDIAN + } fields; +} pore_memory_reloc_t; + + + +typedef union pore_i2c_en_param { + + 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 i2c_engine_identifier : 4; + uint64_t reserved0 : 1; + uint64_t i2c_engine_address_range : 3; + uint64_t reserved1 : 3; + uint64_t i2c_engine_port : 5; + uint64_t reserved2 : 1; + uint64_t i2c_engine_device_id : 7; + uint64_t reserved3 : 2; + uint64_t i2c_engine_speed : 2; + uint64_t i2c_poll_threshold : 4; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t i2c_poll_threshold : 4; + uint64_t i2c_engine_speed : 2; + uint64_t reserved3 : 2; + uint64_t i2c_engine_device_id : 7; + uint64_t reserved2 : 1; + uint64_t i2c_engine_port : 5; + uint64_t reserved1 : 3; + uint64_t i2c_engine_address_range : 3; + uint64_t reserved0 : 1; + uint64_t i2c_engine_identifier : 4; +#endif // _BIG_ENDIAN + } fields; +} pore_i2c_en_param_t; + + +#endif // __ASSEMBLER__ +#endif // __PORE_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/pore_register_addresses.h b/src/ssx/pgp/registers/pore_register_addresses.h new file mode 100755 index 0000000..0fc769b --- /dev/null +++ b/src/ssx/pgp/registers/pore_register_addresses.h @@ -0,0 +1,130 @@ +#ifndef __PORE_REGISTER_ADDRESSES_H__ +#define __PORE_REGISTER_ADDRESSES_H__ + +// $Id: pore_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/pore_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file pore_register_addresses.h +/// \brief Symbolic addresses for the PORE unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define PORE_GPE0_OCI_BASE 0x40000000 +#define PORE_GPE1_OCI_BASE 0x40000100 +#define PORE_SLW_OCI_BASE 0x40040000 +#define PORE_STATUS_OFFSET 0x00000000 +#define PORE_GPE0_STATUS 0x40000000 +#define PORE_GPE1_STATUS 0x40000100 +#define PORE_SLW_STATUS 0x40040000 +#define PORE_CONTROL_OFFSET 0x00000008 +#define PORE_GPE0_CONTROL 0x40000008 +#define PORE_GPE1_CONTROL 0x40000108 +#define PORE_SLW_CONTROL 0x40040008 +#define PORE_RESET_OFFSET 0x00000010 +#define PORE_GPE0_RESET 0x40000010 +#define PORE_GPE1_RESET 0x40000110 +#define PORE_SLW_RESET 0x40040010 +#define PORE_ERROR_MASK_OFFSET 0x00000018 +#define PORE_GPE0_ERROR_MASK 0x40000018 +#define PORE_GPE1_ERROR_MASK 0x40000118 +#define PORE_SLW_ERROR_MASK 0x40040018 +#define PORE_PRV_BASE_ADDRESS0_OFFSET 0x00000020 +#define PORE_GPE0_PRV_BASE_ADDRESS0 0x40000020 +#define PORE_GPE1_PRV_BASE_ADDRESS0 0x40000120 +#define PORE_SLW_PRV_BASE_ADDRESS0 0x40040020 +#define PORE_PRV_BASE_ADDRESS1_OFFSET 0x00000028 +#define PORE_GPE0_PRV_BASE_ADDRESS1 0x40000028 +#define PORE_GPE1_PRV_BASE_ADDRESS1 0x40000128 +#define PORE_SLW_PRV_BASE_ADDRESS1 0x40040028 +#define PORE_OCI_BASE_ADDRESS0_OFFSET 0x00000030 +#define PORE_GPE0_OCI_BASE_ADDRESS0 0x40000030 +#define PORE_GPE1_OCI_BASE_ADDRESS0 0x40000130 +#define PORE_SLW_OCI_BASE_ADDRESS0 0x40040030 +#define PORE_OCI_BASE_ADDRESS1_OFFSET 0x00000038 +#define PORE_GPE0_OCI_BASE_ADDRESS1 0x40000038 +#define PORE_GPE1_OCI_BASE_ADDRESS1 0x40000138 +#define PORE_SLW_OCI_BASE_ADDRESS1 0x40040038 +#define PORE_TABLE_BASE_ADDR_OFFSET 0x00000040 +#define PORE_GPE0_TABLE_BASE_ADDR 0x40000040 +#define PORE_GPE1_TABLE_BASE_ADDR 0x40000140 +#define PORE_SLW_TABLE_BASE_ADDR 0x40040040 +#define PORE_EXE_TRIGGER_OFFSET 0x00000048 +#define PORE_GPE0_EXE_TRIGGER 0x40000048 +#define PORE_GPE1_EXE_TRIGGER 0x40000148 +#define PORE_SLW_EXE_TRIGGER 0x40040048 +#define PORE_SCRATCH0_OFFSET 0x00000050 +#define PORE_GPE0_SCRATCH0 0x40000050 +#define PORE_GPE1_SCRATCH0 0x40000150 +#define PORE_SLW_SCRATCH0 0x40040050 +#define PORE_SCRATCH1_OFFSET 0x00000058 +#define PORE_GPE0_SCRATCH1 0x40000058 +#define PORE_GPE1_SCRATCH1 0x40000158 +#define PORE_SLW_SCRATCH1 0x40040058 +#define PORE_SCRATCH2_OFFSET 0x00000060 +#define PORE_GPE0_SCRATCH2 0x40000060 +#define PORE_GPE1_SCRATCH2 0x40000160 +#define PORE_SLW_SCRATCH2 0x40040060 +#define PORE_IBUF_01_OFFSET 0x00000068 +#define PORE_GPE0_IBUF_01 0x40000068 +#define PORE_GPE1_IBUF_01 0x40000168 +#define PORE_SLW_IBUF_01 0x40040068 +#define PORE_IBUF_2_OFFSET 0x00000070 +#define PORE_GPE0_IBUF_2 0x40000070 +#define PORE_GPE1_IBUF_2 0x40000170 +#define PORE_SLW_IBUF_2 0x40040070 +#define PORE_DBG0_OFFSET 0x00000078 +#define PORE_GPE0_DBG0 0x40000078 +#define PORE_GPE1_DBG0 0x40000178 +#define PORE_SLW_DBG0 0x40040078 +#define PORE_DBG1_OFFSET 0x00000080 +#define PORE_GPE0_DBG1 0x40000080 +#define PORE_GPE1_DBG1 0x40000180 +#define PORE_SLW_DBG1 0x40040080 +#define PORE_PC_STACK0_OFFSET 0x00000088 +#define PORE_GPE0_PC_STACK0 0x40000088 +#define PORE_GPE1_PC_STACK0 0x40000188 +#define PORE_SLW_PC_STACK0 0x40040088 +#define PORE_PC_STACK1_OFFSET 0x00000090 +#define PORE_GPE0_PC_STACK1 0x40000090 +#define PORE_GPE1_PC_STACK1 0x40000190 +#define PORE_SLW_PC_STACK1 0x40040090 +#define PORE_PC_STACK2_OFFSET 0x00000098 +#define PORE_GPE0_PC_STACK2 0x40000098 +#define PORE_GPE1_PC_STACK2 0x40000198 +#define PORE_SLW_PC_STACK2 0x40040098 +#define PORE_ID_FLAGS_OFFSET 0x000000a0 +#define PORE_GPE0_ID_FLAGS 0x400000a0 +#define PORE_GPE1_ID_FLAGS 0x400001a0 +#define PORE_SLW_ID_FLAGS 0x400400a0 +#define PORE_DATA0_OFFSET 0x000000a8 +#define PORE_GPE0_DATA0 0x400000a8 +#define PORE_GPE1_DATA0 0x400001a8 +#define PORE_SLW_DATA0 0x400400a8 +#define PORE_MEMORY_RELOC_OFFSET 0x000000b0 +#define PORE_GPE0_MEMORY_RELOC 0x400000b0 +#define PORE_GPE1_MEMORY_RELOC 0x400001b0 +#define PORE_SLW_MEMORY_RELOC 0x400400b0 +#define PORE_I2C_E0_PARAM_OFFSET 0x000000b8 +#define PORE_I2C_E1_PARAM_OFFSET 0x000000c0 +#define PORE_I2C_E2_PARAM_OFFSET 0x000000c8 +#define PORE_GPE0_I2C_EN_PARAM(n) (PORE_GPE0_I2C_E0_PARAM + ((PORE_GPE0_I2C_E1_PARAM - PORE_GPE0_I2C_E0_PARAM) * (n))) +#define PORE_GPE1_I2C_EN_PARAM(n) (PORE_GPE1_I2C_E0_PARAM + ((PORE_GPE1_I2C_E1_PARAM - PORE_GPE1_I2C_E0_PARAM) * (n))) +#define PORE_SLW_I2C_EN_PARAM(n) (PORE_SLW_I2C_E0_PARAM + ((PORE_SLW_I2C_E1_PARAM - PORE_SLW_I2C_E0_PARAM) * (n))) +#define PORE_GPE0_I2C_E0_PARAM 0x400000b8 +#define PORE_GPE1_I2C_E0_PARAM 0x400001b8 +#define PORE_SLW_I2C_E0_PARAM 0x400400b8 +#define PORE_GPE0_I2C_E1_PARAM 0x400000c0 +#define PORE_GPE1_I2C_E1_PARAM 0x400001c0 +#define PORE_SLW_I2C_E1_PARAM 0x400400c0 +#define PORE_GPE0_I2C_E2_PARAM 0x400000c8 +#define PORE_GPE1_I2C_E2_PARAM 0x400001c8 +#define PORE_SLW_I2C_E2_PARAM 0x400400c8 + +#endif // __PORE_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/sbe_firmware_registers.h b/src/ssx/pgp/registers/sbe_firmware_registers.h new file mode 100644 index 0000000..8175c11 --- /dev/null +++ b/src/ssx/pgp/registers/sbe_firmware_registers.h @@ -0,0 +1,906 @@ +#ifndef __SBE_FIRMWARE_REGISTERS_H__ +#define __SBE_FIRMWARE_REGISTERS_H__ + +// $Id: sbe_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/sbe_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file sbe_firmware_registers.h +/// \brief C register structs for the SBE unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union pore_sbe_status { + + 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 cur_state : 8; + uint64_t freeze_action : 1; + uint64_t interrupt_pending : 1; + uint64_t spare : 2; + uint64_t stack_pointer : 4; + uint64_t pc : 48; +#else + uint64_t pc : 48; + uint64_t stack_pointer : 4; + uint64_t spare : 2; + uint64_t interrupt_pending : 1; + uint64_t freeze_action : 1; + uint64_t cur_state : 8; +#endif // _BIG_ENDIAN + } fields; +} pore_sbe_status_t; + +#endif // __ASSEMBLER__ +#define PORE_SBE_STATUS_CUR_STATE_MASK SIXTYFOUR_BIT_CONSTANT(0xff00000000000000) +#define PORE_SBE_STATUS_FREEZE_ACTION SIXTYFOUR_BIT_CONSTANT(0x0080000000000000) +#define PORE_SBE_STATUS_INTERRUPT_PENDING SIXTYFOUR_BIT_CONSTANT(0x0040000000000000) +#define PORE_SBE_STATUS_SPARE_MASK SIXTYFOUR_BIT_CONSTANT(0x0030000000000000) +#define PORE_SBE_STATUS_STACK_POINTER_MASK SIXTYFOUR_BIT_CONSTANT(0x000f000000000000) +#define PORE_SBE_STATUS_PC_MASK SIXTYFOUR_BIT_CONSTANT(0xffffffffffffffff) +#ifndef __ASSEMBLER__ + + +typedef union pore_sbe_control { + + 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 start_stop : 1; + uint64_t continue_step : 1; + uint64_t skip : 1; + uint64_t set_pc : 1; + uint64_t set_tp_scan_clk : 3; + uint64_t lock_exe_trig : 1; + uint64_t freeze_mask : 1; + uint64_t check_parity : 1; + uint64_t prv_parity : 1; + uint64_t trap_enable : 1; + uint64_t narrow_mode_trace : 1; + uint64_t interruptible : 1; + uint64_t pore_done_override : 1; + uint64_t interruptible_en : 1; + uint64_t pc_brk_pt : 48; +#else + uint64_t pc_brk_pt : 48; + uint64_t interruptible_en : 1; + uint64_t pore_done_override : 1; + uint64_t interruptible : 1; + uint64_t narrow_mode_trace : 1; + 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 // _BIG_ENDIAN + } fields; +} pore_sbe_control_t; + +#endif // __ASSEMBLER__ +#define PORE_SBE_CONTROL_START_STOP SIXTYFOUR_BIT_CONSTANT(0x8000000000000000) +#define PORE_SBE_CONTROL_CONTINUE_STEP SIXTYFOUR_BIT_CONSTANT(0x4000000000000000) +#define PORE_SBE_CONTROL_SKIP SIXTYFOUR_BIT_CONSTANT(0x2000000000000000) +#define PORE_SBE_CONTROL_SET_PC SIXTYFOUR_BIT_CONSTANT(0x1000000000000000) +#define PORE_SBE_CONTROL_SET_TP_SCAN_CLK_MASK SIXTYFOUR_BIT_CONSTANT(0x0e00000000000000) +#define PORE_SBE_CONTROL_LOCK_EXE_TRIG SIXTYFOUR_BIT_CONSTANT(0x0100000000000000) +#define PORE_SBE_CONTROL_FREEZE_MASK SIXTYFOUR_BIT_CONSTANT(0x0080000000000000) +#define PORE_SBE_CONTROL_CHECK_PARITY SIXTYFOUR_BIT_CONSTANT(0x0040000000000000) +#define PORE_SBE_CONTROL_PRV_PARITY SIXTYFOUR_BIT_CONSTANT(0x0020000000000000) +#define PORE_SBE_CONTROL_TRAP_ENABLE SIXTYFOUR_BIT_CONSTANT(0x0010000000000000) +#define PORE_SBE_CONTROL_NARROW_MODE_TRACE SIXTYFOUR_BIT_CONSTANT(0x0008000000000000) +#define PORE_SBE_CONTROL_INTERRUPTIBLE SIXTYFOUR_BIT_CONSTANT(0x0004000000000000) +#define PORE_SBE_CONTROL_PORE_DONE_OVERRIDE SIXTYFOUR_BIT_CONSTANT(0x0002000000000000) +#define PORE_SBE_CONTROL_INTERRUPTIBLE_EN SIXTYFOUR_BIT_CONSTANT(0x0001000000000000) +#define PORE_SBE_CONTROL_PC_BRK_PT_MASK SIXTYFOUR_BIT_CONSTANT(0xffffffffffffffff) +#ifndef __ASSEMBLER__ + + +typedef union pore_sbe_reset { + + 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 fn_reset : 1; + uint64_t oci_reset : 1; + uint64_t _reserved0 : 62; +#else + uint64_t _reserved0 : 62; + uint64_t oci_reset : 1; + uint64_t fn_reset : 1; +#endif // _BIG_ENDIAN + } fields; +} pore_sbe_reset_t; + + + +typedef union pore_sbe_error_mask { + + 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 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_err_output0 : 1; + uint64_t enable_fatal_err_output1 : 1; + uint64_t enable_fatal_err_output2 : 1; + uint64_t enable_fatal_err_output3 : 1; + uint64_t enable_fatal_err_output4 : 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 i2c_bad_status_0 : 1; + uint64_t i2c_bad_status_1 : 1; + uint64_t i2c_bad_status_2 : 1; + uint64_t i2c_bad_status_3 : 1; + uint64_t group_parity_error_0 : 1; + uint64_t group_parity_error_1 : 1; + uint64_t group_parity_error_2 : 1; + uint64_t group_parity_error_3 : 1; + uint64_t group_parity_error_4 : 1; + uint64_t _reserved0 : 34; +#else + uint64_t _reserved0 : 34; + uint64_t group_parity_error_4 : 1; + uint64_t group_parity_error_3 : 1; + uint64_t group_parity_error_2 : 1; + uint64_t group_parity_error_1 : 1; + uint64_t group_parity_error_0 : 1; + uint64_t i2c_bad_status_3 : 1; + uint64_t i2c_bad_status_2 : 1; + uint64_t i2c_bad_status_1 : 1; + uint64_t i2c_bad_status_0 : 1; + 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_err_output4 : 1; + uint64_t enable_fatal_err_output3 : 1; + uint64_t enable_fatal_err_output2 : 1; + uint64_t enable_fatal_err_output1 : 1; + uint64_t enable_fatal_err_output0 : 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 // _BIG_ENDIAN + } fields; +} pore_sbe_error_mask_t; + +#endif // __ASSEMBLER__ +#define PORE_SBE_ERROR_MASK_ENABLE_ERR_HANDLER0 SIXTYFOUR_BIT_CONSTANT(0x8000000000000000) +#define PORE_SBE_ERROR_MASK_ENABLE_ERR_HANDLER1 SIXTYFOUR_BIT_CONSTANT(0x4000000000000000) +#define PORE_SBE_ERROR_MASK_ENABLE_ERR_HANDLER2 SIXTYFOUR_BIT_CONSTANT(0x2000000000000000) +#define PORE_SBE_ERROR_MASK_ENABLE_ERR_HANDLER3 SIXTYFOUR_BIT_CONSTANT(0x1000000000000000) +#define PORE_SBE_ERROR_MASK_ENABLE_ERR_HANDLER4 SIXTYFOUR_BIT_CONSTANT(0x0800000000000000) +#define PORE_SBE_ERROR_MASK_ENABLE_ERR_OUTPUT0 SIXTYFOUR_BIT_CONSTANT(0x0400000000000000) +#define PORE_SBE_ERROR_MASK_ENABLE_ERR_OUTPUT1 SIXTYFOUR_BIT_CONSTANT(0x0200000000000000) +#define PORE_SBE_ERROR_MASK_ENABLE_ERR_OUTPUT2 SIXTYFOUR_BIT_CONSTANT(0x0100000000000000) +#define PORE_SBE_ERROR_MASK_ENABLE_ERR_OUTPUT3 SIXTYFOUR_BIT_CONSTANT(0x0080000000000000) +#define PORE_SBE_ERROR_MASK_ENABLE_ERR_OUTPUT4 SIXTYFOUR_BIT_CONSTANT(0x0040000000000000) +#define PORE_SBE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT0 SIXTYFOUR_BIT_CONSTANT(0x0020000000000000) +#define PORE_SBE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT1 SIXTYFOUR_BIT_CONSTANT(0x0010000000000000) +#define PORE_SBE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT2 SIXTYFOUR_BIT_CONSTANT(0x0008000000000000) +#define PORE_SBE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT3 SIXTYFOUR_BIT_CONSTANT(0x0004000000000000) +#define PORE_SBE_ERROR_MASK_ENABLE_FATAL_ERR_OUTPUT4 SIXTYFOUR_BIT_CONSTANT(0x0002000000000000) +#define PORE_SBE_ERROR_MASK_STOP_EXE_ON_ERROR0 SIXTYFOUR_BIT_CONSTANT(0x0001000000000000) +#define PORE_SBE_ERROR_MASK_STOP_EXE_ON_ERROR1 SIXTYFOUR_BIT_CONSTANT(0x0000800000000000) +#define PORE_SBE_ERROR_MASK_STOP_EXE_ON_ERROR2 SIXTYFOUR_BIT_CONSTANT(0x0000400000000000) +#define PORE_SBE_ERROR_MASK_STOP_EXE_ON_ERROR3 SIXTYFOUR_BIT_CONSTANT(0x0000200000000000) +#define PORE_SBE_ERROR_MASK_STOP_EXE_ON_ERROR4 SIXTYFOUR_BIT_CONSTANT(0x0000100000000000) +#define PORE_SBE_ERROR_MASK_GATE_CHIPLET_OFFLINE_ERR SIXTYFOUR_BIT_CONSTANT(0x0000080000000000) +#define PORE_SBE_ERROR_MASK_I2C_BAD_STATUS_0 SIXTYFOUR_BIT_CONSTANT(0x0000040000000000) +#define PORE_SBE_ERROR_MASK_I2C_BAD_STATUS_1 SIXTYFOUR_BIT_CONSTANT(0x0000020000000000) +#define PORE_SBE_ERROR_MASK_I2C_BAD_STATUS_2 SIXTYFOUR_BIT_CONSTANT(0x0000010000000000) +#define PORE_SBE_ERROR_MASK_I2C_BAD_STATUS_3 SIXTYFOUR_BIT_CONSTANT(0x0000008000000000) +#define PORE_SBE_ERROR_MASK_GROUP_PARITY_ERROR_0 SIXTYFOUR_BIT_CONSTANT(0x0000004000000000) +#define PORE_SBE_ERROR_MASK_GROUP_PARITY_ERROR_1 SIXTYFOUR_BIT_CONSTANT(0x0000002000000000) +#define PORE_SBE_ERROR_MASK_GROUP_PARITY_ERROR_2 SIXTYFOUR_BIT_CONSTANT(0x0000001000000000) +#define PORE_SBE_ERROR_MASK_GROUP_PARITY_ERROR_3 SIXTYFOUR_BIT_CONSTANT(0x0000000800000000) +#define PORE_SBE_ERROR_MASK_GROUP_PARITY_ERROR_4 SIXTYFOUR_BIT_CONSTANT(0x0000000400000000) +#ifndef __ASSEMBLER__ + + +typedef union pore_sbe_prv_base_address0 { + + 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 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 // _BIG_ENDIAN + } fields; +} pore_sbe_prv_base_address0_t; + + + +typedef union pore_sbe_prv_base_address1 { + + 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 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 // _BIG_ENDIAN + } fields; +} pore_sbe_prv_base_address1_t; + + + +typedef union pore_sbe_oci_base_address0 { + + 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 spare : 18; + uint64_t oci_mem_route : 14; + uint64_t oci_base_address : 32; +#else + uint64_t oci_base_address : 32; + uint64_t oci_mem_route : 14; + uint64_t spare : 18; +#endif // _BIG_ENDIAN + } fields; +} pore_sbe_oci_base_address0_t; + + + +typedef union pore_sbe_oci_base_address1 { + + 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 spare : 18; + uint64_t oci_mem_route : 14; + uint64_t oci_base_address : 32; +#else + uint64_t oci_base_address : 32; + uint64_t oci_mem_route : 14; + uint64_t spare : 18; +#endif // _BIG_ENDIAN + } fields; +} pore_sbe_oci_base_address1_t; + + + +typedef union pore_sbe_table_base_addr { + + 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 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 // _BIG_ENDIAN + } fields; +} pore_sbe_table_base_addr_t; + + + +typedef union pore_sbe_exe_trigger { + + 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 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 // _BIG_ENDIAN + } fields; +} pore_sbe_exe_trigger_t; + + + +typedef union pore_sbe_scratch0 { + + 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 zeroes : 8; + uint64_t scratch0 : 24; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t scratch0 : 24; + uint64_t zeroes : 8; +#endif // _BIG_ENDIAN + } fields; +} pore_sbe_scratch0_t; + + + +typedef union pore_sbe_scratch1 { + + 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 scratch1 : 64; +#else + uint64_t scratch1 : 64; +#endif // _BIG_ENDIAN + } fields; +} pore_sbe_scratch1_t; + + + +typedef union pore_sbe_scratch2 { + + 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 scratch2 : 64; +#else + uint64_t scratch2 : 64; +#endif // _BIG_ENDIAN + } fields; +} pore_sbe_scratch2_t; + + + +typedef union pore_sbe_ibuf_01 { + + 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 ibuf0 : 32; + uint64_t ibuf1 : 32; +#else + uint64_t ibuf1 : 32; + uint64_t ibuf0 : 32; +#endif // _BIG_ENDIAN + } fields; +} pore_sbe_ibuf_01_t; + + + +typedef union pore_sbe_ibuf_2 { + + 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 ibuf2 : 32; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t ibuf2 : 32; +#endif // _BIG_ENDIAN + } fields; +} pore_sbe_ibuf_2_t; + + + +typedef union pore_sbe_dbg0 { + + 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 last_completed_address : 32; + uint64_t last_pib_parity_fail : 1; + uint64_t last_ret_code_prv : 3; + uint64_t i2c_bad_status0 : 1; + uint64_t i2c_bad_status1 : 1; + uint64_t i2c_bad_status2 : 1; + uint64_t i2c_bad_status3 : 1; + uint64_t group_parity_error0 : 1; + uint64_t group_parity_error1 : 1; + uint64_t group_parity_error2 : 1; + uint64_t group_parity_error3 : 1; + uint64_t group_parity_error4 : 1; + uint64_t interrupt_counter : 8; + uint64_t _reserved0 : 11; +#else + uint64_t _reserved0 : 11; + uint64_t interrupt_counter : 8; + uint64_t group_parity_error4 : 1; + uint64_t group_parity_error3 : 1; + uint64_t group_parity_error2 : 1; + uint64_t group_parity_error1 : 1; + uint64_t group_parity_error0 : 1; + uint64_t i2c_bad_status3 : 1; + uint64_t i2c_bad_status2 : 1; + uint64_t i2c_bad_status1 : 1; + uint64_t i2c_bad_status0 : 1; + uint64_t last_ret_code_prv : 3; + uint64_t last_pib_parity_fail : 1; + uint64_t last_completed_address : 32; +#endif // _BIG_ENDIAN + } fields; +} pore_sbe_dbg0_t; + + + +typedef union pore_sbe_dbg1 { + + 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 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 fast_i2c_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 fast_i2c_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 // _BIG_ENDIAN + } fields; +} pore_sbe_dbg1_t; + + + +typedef union pore_sbe_pc_stack0 { + + 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 pc_stack0 : 48; + uint64_t _reserved0 : 11; + uint64_t set_new_stack_pointer : 1; + uint64_t new_stack_pointer : 4; +#else + uint64_t new_stack_pointer : 4; + uint64_t set_new_stack_pointer : 1; + uint64_t _reserved0 : 11; + uint64_t pc_stack0 : 48; +#endif // _BIG_ENDIAN + } fields; +} pore_sbe_pc_stack0_t; + + + +typedef union pore_sbe_pc_stack1 { + + 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 pc_stack1 : 48; + uint64_t _reserved0 : 16; +#else + uint64_t _reserved0 : 16; + uint64_t pc_stack1 : 48; +#endif // _BIG_ENDIAN + } fields; +} pore_sbe_pc_stack1_t; + + + +typedef union pore_sbe_pc_stack2 { + + 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 pc_stack2 : 48; + uint64_t _reserved0 : 16; +#else + uint64_t _reserved0 : 16; + uint64_t pc_stack2 : 48; +#endif // _BIG_ENDIAN + } fields; +} pore_sbe_pc_stack2_t; + + + +typedef union pore_sbe_id_flags { + + 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 reserved0 : 32; + uint64_t pib_parity_fail : 1; + uint64_t pib_status : 3; + uint64_t oci_parity_fail : 1; + uint64_t oci_status : 3; + uint64_t reserved1 : 8; + uint64_t ugt : 1; + uint64_t ult : 1; + uint64_t sgt : 1; + uint64_t slt : 1; + uint64_t c : 1; + uint64_t o : 1; + uint64_t n : 1; + uint64_t z : 1; + uint64_t reserved2 : 4; + uint64_t ibuf_id : 4; +#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 // _BIG_ENDIAN + } fields; +} pore_sbe_id_flags_t; + + + +typedef union pore_sbe_data0 { + + 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 data0 : 32; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t data0 : 32; +#endif // _BIG_ENDIAN + } fields; +} pore_sbe_data0_t; + + + +typedef union pore_sbe_memory_reloc { + + 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 _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 // _BIG_ENDIAN + } fields; +} pore_sbe_memory_reloc_t; + + + +typedef union pore_sbe_i2c_en_param { + + 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 i2c_engine_identifier : 4; + uint64_t reserved0 : 1; + uint64_t i2c_engine_address_range : 3; + uint64_t reserved1 : 3; + uint64_t i2c_engine_port : 5; + uint64_t reserved2 : 1; + uint64_t i2c_engine_device_id : 7; + uint64_t reserved3 : 2; + uint64_t i2c_engine_speed : 2; + uint64_t i2c_poll_threshold : 4; + uint64_t _reserved0 : 32; +#else + uint64_t _reserved0 : 32; + uint64_t i2c_poll_threshold : 4; + uint64_t i2c_engine_speed : 2; + uint64_t reserved3 : 2; + uint64_t i2c_engine_device_id : 7; + uint64_t reserved2 : 1; + uint64_t i2c_engine_port : 5; + uint64_t reserved1 : 3; + uint64_t i2c_engine_address_range : 3; + uint64_t reserved0 : 1; + uint64_t i2c_engine_identifier : 4; +#endif // _BIG_ENDIAN + } fields; +} pore_sbe_i2c_en_param_t; + + +#endif // __ASSEMBLER__ +#endif // __SBE_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/sbe_register_addresses.h b/src/ssx/pgp/registers/sbe_register_addresses.h new file mode 100644 index 0000000..794acea --- /dev/null +++ b/src/ssx/pgp/registers/sbe_register_addresses.h @@ -0,0 +1,48 @@ +#ifndef __SBE_REGISTER_ADDRESSES_H__ +#define __SBE_REGISTER_ADDRESSES_H__ + +// $Id: sbe_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/sbe_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file sbe_register_addresses.h +/// \brief Symbolic addresses for the SBE unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define PORE_SBE_PIB_BASE 0x000e0000 +#define PORE_SBE_STATUS 0x000e0000 +#define PORE_SBE_CONTROL 0x000e0001 +#define PORE_SBE_RESET 0x000e0002 +#define PORE_SBE_ERROR_MASK 0x000e0003 +#define PORE_SBE_PRV_BASE_ADDRESS0 0x000e0004 +#define PORE_SBE_PRV_BASE_ADDRESS1 0x000e0005 +#define PORE_SBE_OCI_BASE_ADDRESS0 0x000e0006 +#define PORE_SBE_OCI_BASE_ADDRESS1 0x000e0007 +#define PORE_SBE_TABLE_BASE_ADDR 0x000e0008 +#define PORE_SBE_EXE_TRIGGER 0x000e0009 +#define PORE_SBE_SCRATCH0 0x000e000a +#define PORE_SBE_SCRATCH1 0x000e000b +#define PORE_SBE_SCRATCH2 0x000e000c +#define PORE_SBE_IBUF_01 0x000e000d +#define PORE_SBE_IBUF_2 0x000e000e +#define PORE_SBE_DBG0 0x000e000f +#define PORE_SBE_DBG1 0x000e0010 +#define PORE_SBE_PC_STACK0 0x000e0011 +#define PORE_SBE_PC_STACK1 0x000e0012 +#define PORE_SBE_PC_STACK2 0x000e0013 +#define PORE_SBE_ID_FLAGS 0x000e0014 +#define PORE_SBE_DATA0 0x000e0015 +#define PORE_SBE_MEMORY_RELOC 0x000e0016 +#define PORE_SBE_I2C_EN_PARAM(n) (PORE_SBE_I2C_E0_PARAM + ((PORE_SBE_I2C_E1_PARAM - PORE_SBE_I2C_E0_PARAM) * (n))) +#define PORE_SBE_I2C_E0_PARAM 0x000e0017 +#define PORE_SBE_I2C_E1_PARAM 0x000e0018 +#define PORE_SBE_I2C_E2_PARAM 0x000e0019 + +#endif // __SBE_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/sensors_firmware_registers.h b/src/ssx/pgp/registers/sensors_firmware_registers.h new file mode 100755 index 0000000..9cb252e --- /dev/null +++ b/src/ssx/pgp/registers/sensors_firmware_registers.h @@ -0,0 +1,668 @@ +#ifndef __SENSORS_FIRMWARE_REGISTERS_H__ +#define __SENSORS_FIRMWARE_REGISTERS_H__ + +// $Id: sensors_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/sensors_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file sensors_firmware_registers.h +/// \brief C register structs for the SENSORS unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union sensors_v0 { + + 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 dts0 : 12; + uint64_t thermal_trip0 : 2; + uint64_t spare0 : 1; + uint64_t valid0 : 1; + uint64_t dts1 : 12; + uint64_t thermal_trip1 : 2; + uint64_t spare1 : 1; + uint64_t valid1 : 1; + uint64_t dts2 : 12; + uint64_t thermal_trip2 : 2; + uint64_t spare2 : 1; + uint64_t valid2 : 1; + uint64_t dts3 : 12; + uint64_t thermal_trip3 : 2; + uint64_t spare3 : 1; + uint64_t valid3 : 1; +#else + uint64_t valid3 : 1; + uint64_t spare3 : 1; + uint64_t thermal_trip3 : 2; + uint64_t dts3 : 12; + uint64_t valid2 : 1; + uint64_t spare2 : 1; + uint64_t thermal_trip2 : 2; + uint64_t dts2 : 12; + uint64_t valid1 : 1; + uint64_t spare1 : 1; + uint64_t thermal_trip1 : 2; + uint64_t dts1 : 12; + uint64_t valid0 : 1; + uint64_t spare0 : 1; + uint64_t thermal_trip0 : 2; + uint64_t dts0 : 12; +#endif // _BIG_ENDIAN + } fields; +} sensors_v0_t; + + + +typedef union sensors_v1 { + + 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 dts4 : 12; + uint64_t thermal_trip4 : 2; + uint64_t spare4 : 1; + uint64_t valid4 : 1; + uint64_t dts5 : 12; + uint64_t thermal_trip5 : 2; + uint64_t spare5 : 1; + uint64_t valid5 : 1; + uint64_t dts6 : 12; + uint64_t thermal_trip6 : 2; + uint64_t spare6 : 1; + uint64_t valid6 : 1; + uint64_t dts7 : 12; + uint64_t thermal_trip7 : 2; + uint64_t spare7 : 1; + uint64_t valid7 : 1; +#else + uint64_t valid7 : 1; + uint64_t spare7 : 1; + uint64_t thermal_trip7 : 2; + uint64_t dts7 : 12; + uint64_t valid6 : 1; + uint64_t spare6 : 1; + uint64_t thermal_trip6 : 2; + uint64_t dts6 : 12; + uint64_t valid5 : 1; + uint64_t spare5 : 1; + uint64_t thermal_trip5 : 2; + uint64_t dts5 : 12; + uint64_t valid4 : 1; + uint64_t spare4 : 1; + uint64_t thermal_trip4 : 2; + uint64_t dts4 : 12; +#endif // _BIG_ENDIAN + } fields; +} sensors_v1_t; + + + +typedef union sensors_v2 { + + 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 dts8 : 12; + uint64_t thermal_trip8 : 2; + uint64_t spare8 : 1; + uint64_t valid8 : 1; + uint64_t dts9 : 12; + uint64_t thermal_trip9 : 2; + uint64_t spare9 : 1; + uint64_t valid9 : 1; + uint64_t dts10 : 12; + uint64_t thermal_trip10 : 2; + uint64_t spare10 : 1; + uint64_t valid10 : 1; + uint64_t dts12 : 12; + uint64_t thermal_trip12 : 2; + uint64_t spare12 : 1; + uint64_t valid12 : 1; +#else + uint64_t valid12 : 1; + uint64_t spare12 : 1; + uint64_t thermal_trip12 : 2; + uint64_t dts12 : 12; + uint64_t valid10 : 1; + uint64_t spare10 : 1; + uint64_t thermal_trip10 : 2; + uint64_t dts10 : 12; + uint64_t valid9 : 1; + uint64_t spare9 : 1; + uint64_t thermal_trip9 : 2; + uint64_t dts9 : 12; + uint64_t valid8 : 1; + uint64_t spare8 : 1; + uint64_t thermal_trip8 : 2; + uint64_t dts8 : 12; +#endif // _BIG_ENDIAN + } fields; +} sensors_v2_t; + + + +typedef union sensors_v3 { + + 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 unknown : 64; +#else + uint64_t unknown : 64; +#endif // _BIG_ENDIAN + } fields; +} sensors_v3_t; + + + +typedef union sensors_v5 { + + 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 raw_cpm0 : 12; + uint64_t spare0 : 4; + uint64_t raw_cpm1 : 12; + uint64_t spare1 : 4; + uint64_t raw_cpm2 : 12; + uint64_t spare2 : 4; + uint64_t raw_cpm3 : 12; + uint64_t spare3 : 4; +#else + uint64_t spare3 : 4; + uint64_t raw_cpm3 : 12; + uint64_t spare2 : 4; + uint64_t raw_cpm2 : 12; + uint64_t spare1 : 4; + uint64_t raw_cpm1 : 12; + uint64_t spare0 : 4; + uint64_t raw_cpm0 : 12; +#endif // _BIG_ENDIAN + } fields; +} sensors_v5_t; + + + +typedef union sensors_v6 { + + 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 raw_cpm4 : 12; + uint64_t spare4 : 4; + uint64_t raw_cpm5 : 12; + uint64_t spare5 : 4; + uint64_t raw_cpm6 : 12; + uint64_t spare6 : 4; + uint64_t raw_cpm7 : 12; + uint64_t spare7 : 4; +#else + uint64_t spare7 : 4; + uint64_t raw_cpm7 : 12; + uint64_t spare6 : 4; + uint64_t raw_cpm6 : 12; + uint64_t spare5 : 4; + uint64_t raw_cpm5 : 12; + uint64_t spare4 : 4; + uint64_t raw_cpm4 : 12; +#endif // _BIG_ENDIAN + } fields; +} sensors_v6_t; + + + +typedef union sensors_v7 { + + 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 raw_cpm8 : 12; + uint64_t spare8 : 4; + uint64_t raw_cpm9 : 12; + uint64_t spare9 : 4; + uint64_t raw_cpm10 : 12; + uint64_t spare10 : 4; + uint64_t raw_cpm11 : 12; + uint64_t spare11 : 4; +#else + uint64_t spare11 : 4; + uint64_t raw_cpm11 : 12; + uint64_t spare10 : 4; + uint64_t raw_cpm10 : 12; + uint64_t spare9 : 4; + uint64_t raw_cpm9 : 12; + uint64_t spare8 : 4; + uint64_t raw_cpm8 : 12; +#endif // _BIG_ENDIAN + } fields; +} sensors_v7_t; + + + +typedef union sensors_v8 { + + 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 dts0 : 12; + uint64_t thermal_trip0 : 2; + uint64_t spare0 : 1; + uint64_t valid0 : 1; + uint64_t dts1 : 12; + uint64_t thermal_trip1 : 2; + uint64_t spare1 : 1; + uint64_t valid1 : 1; + uint64_t dts2 : 12; + uint64_t thermal_trip2 : 2; + uint64_t spare2 : 1; + uint64_t valid2 : 1; + uint64_t encoded_cpm0 : 4; + uint64_t encoded_cpm1 : 4; + uint64_t encoded_cpm2 : 4; + uint64_t encoded_cpm3 : 4; +#else + uint64_t encoded_cpm3 : 4; + uint64_t encoded_cpm2 : 4; + uint64_t encoded_cpm1 : 4; + uint64_t encoded_cpm0 : 4; + uint64_t valid2 : 1; + uint64_t spare2 : 1; + uint64_t thermal_trip2 : 2; + uint64_t dts2 : 12; + uint64_t valid1 : 1; + uint64_t spare1 : 1; + uint64_t thermal_trip1 : 2; + uint64_t dts1 : 12; + uint64_t valid0 : 1; + uint64_t spare0 : 1; + uint64_t thermal_trip0 : 2; + uint64_t dts0 : 12; +#endif // _BIG_ENDIAN + } fields; +} sensors_v8_t; + + + +typedef union sensors_v9 { + + 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 dts4 : 12; + uint64_t thermal_trip4 : 2; + uint64_t spare4 : 1; + uint64_t valid4 : 1; + uint64_t dts5 : 12; + uint64_t thermal_trip5 : 2; + uint64_t spare5 : 1; + uint64_t valid5 : 1; + uint64_t dts6 : 12; + uint64_t thermal_trip6 : 2; + uint64_t spare6 : 1; + uint64_t valid6 : 1; + uint64_t encoded_cpm4 : 4; + uint64_t encoded_cpm5 : 4; + uint64_t encoded_cpm6 : 4; + uint64_t encoded_cpm7 : 4; +#else + uint64_t encoded_cpm7 : 4; + uint64_t encoded_cpm6 : 4; + uint64_t encoded_cpm5 : 4; + uint64_t encoded_cpm4 : 4; + uint64_t valid6 : 1; + uint64_t spare6 : 1; + uint64_t thermal_trip6 : 2; + uint64_t dts6 : 12; + uint64_t valid5 : 1; + uint64_t spare5 : 1; + uint64_t thermal_trip5 : 2; + uint64_t dts5 : 12; + uint64_t valid4 : 1; + uint64_t spare4 : 1; + uint64_t thermal_trip4 : 2; + uint64_t dts4 : 12; +#endif // _BIG_ENDIAN + } fields; +} sensors_v9_t; + + + +typedef union sensors_v10 { + + 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 dts8 : 12; + uint64_t thermal_trip8 : 2; + uint64_t spare8 : 1; + uint64_t valid8 : 1; + uint64_t dts9 : 12; + uint64_t thermal_trip9 : 2; + uint64_t spare9 : 1; + uint64_t valid9 : 1; + uint64_t dts10 : 12; + uint64_t thermal_trip10 : 2; + uint64_t spare10 : 1; + uint64_t valid10 : 1; + uint64_t encoded_cpm8 : 4; + uint64_t encoded_cpm9 : 4; + uint64_t encoded_cpm10 : 4; + uint64_t encoded_cpm11 : 4; +#else + uint64_t encoded_cpm11 : 4; + uint64_t encoded_cpm10 : 4; + uint64_t encoded_cpm9 : 4; + uint64_t encoded_cpm8 : 4; + uint64_t valid10 : 1; + uint64_t spare10 : 1; + uint64_t thermal_trip10 : 2; + uint64_t dts10 : 12; + uint64_t valid9 : 1; + uint64_t spare9 : 1; + uint64_t thermal_trip9 : 2; + uint64_t dts9 : 12; + uint64_t valid8 : 1; + uint64_t spare8 : 1; + uint64_t thermal_trip8 : 2; + uint64_t dts8 : 12; +#endif // _BIG_ENDIAN + } fields; +} sensors_v10_t; + + + +typedef union sensors_v11 { + + 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 dvs0 : 12; + uint64_t spare00 : 1; + uint64_t trip0 : 1; + uint64_t spare01 : 1; + uint64_t valid0 : 1; + uint64_t dvs1 : 12; + uint64_t spare10 : 1; + uint64_t trip1 : 1; + uint64_t spare11 : 1; + uint64_t valid1 : 1; + uint64_t dvs2 : 12; + uint64_t spare20 : 1; + uint64_t trip2 : 1; + uint64_t spare21 : 1; + uint64_t valid2 : 1; + uint64_t dvs3 : 12; + uint64_t spare30 : 1; + uint64_t trip3 : 1; + uint64_t spare31 : 1; + uint64_t valid3 : 1; +#else + uint64_t valid3 : 1; + uint64_t spare31 : 1; + uint64_t trip3 : 1; + uint64_t spare30 : 1; + uint64_t dvs3 : 12; + uint64_t valid2 : 1; + uint64_t spare21 : 1; + uint64_t trip2 : 1; + uint64_t spare20 : 1; + uint64_t dvs2 : 12; + uint64_t valid1 : 1; + uint64_t spare11 : 1; + uint64_t trip1 : 1; + uint64_t spare10 : 1; + uint64_t dvs1 : 12; + uint64_t valid0 : 1; + uint64_t spare01 : 1; + uint64_t trip0 : 1; + uint64_t spare00 : 1; + uint64_t dvs0 : 12; +#endif // _BIG_ENDIAN + } fields; +} sensors_v11_t; + + + +typedef union sensors_v12 { + + 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 dvs4 : 12; + uint64_t spare40 : 1; + uint64_t trip4 : 1; + uint64_t spare41 : 1; + uint64_t valid4 : 1; + uint64_t dvs5 : 12; + uint64_t spare50 : 1; + uint64_t trip5 : 1; + uint64_t spare51 : 1; + uint64_t valid5 : 1; + uint64_t dvs6 : 12; + uint64_t spare60 : 1; + uint64_t trip6 : 1; + uint64_t spare61 : 1; + uint64_t valid6 : 1; + uint64_t dvs7 : 12; + uint64_t spare70 : 1; + uint64_t trip7 : 1; + uint64_t spare71 : 1; + uint64_t valid7 : 1; +#else + uint64_t valid7 : 1; + uint64_t spare71 : 1; + uint64_t trip7 : 1; + uint64_t spare70 : 1; + uint64_t dvs7 : 12; + uint64_t valid6 : 1; + uint64_t spare61 : 1; + uint64_t trip6 : 1; + uint64_t spare60 : 1; + uint64_t dvs6 : 12; + uint64_t valid5 : 1; + uint64_t spare51 : 1; + uint64_t trip5 : 1; + uint64_t spare50 : 1; + uint64_t dvs5 : 12; + uint64_t valid4 : 1; + uint64_t spare41 : 1; + uint64_t trip4 : 1; + uint64_t spare40 : 1; + uint64_t dvs4 : 12; +#endif // _BIG_ENDIAN + } fields; +} sensors_v12_t; + + + +typedef union sensors_v13 { + + 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 dvs8 : 12; + uint64_t spare80 : 1; + uint64_t trip8 : 1; + uint64_t spare81 : 1; + uint64_t valid8 : 1; + uint64_t dvs9 : 12; + uint64_t spare90 : 1; + uint64_t trip9 : 1; + uint64_t spare91 : 1; + uint64_t valid9 : 1; + uint64_t dvs10 : 12; + uint64_t spare100 : 1; + uint64_t trip10 : 1; + uint64_t spare101 : 1; + uint64_t valid10 : 1; + uint64_t dvs11 : 12; + uint64_t spare110 : 1; + uint64_t trip11 : 1; + uint64_t spare111 : 1; + uint64_t valid11 : 1; +#else + uint64_t valid11 : 1; + uint64_t spare111 : 1; + uint64_t trip11 : 1; + uint64_t spare110 : 1; + uint64_t dvs11 : 12; + uint64_t valid10 : 1; + uint64_t spare101 : 1; + uint64_t trip10 : 1; + uint64_t spare100 : 1; + uint64_t dvs10 : 12; + uint64_t valid9 : 1; + uint64_t spare91 : 1; + uint64_t trip9 : 1; + uint64_t spare90 : 1; + uint64_t dvs9 : 12; + uint64_t valid8 : 1; + uint64_t spare81 : 1; + uint64_t trip8 : 1; + uint64_t spare80 : 1; + uint64_t dvs8 : 12; +#endif // _BIG_ENDIAN + } fields; +} sensors_v13_t; + + +#endif // __ASSEMBLER__ +#endif // __SENSORS_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/sensors_register_addresses.h b/src/ssx/pgp/registers/sensors_register_addresses.h new file mode 100755 index 0000000..c815ace --- /dev/null +++ b/src/ssx/pgp/registers/sensors_register_addresses.h @@ -0,0 +1,47 @@ +#ifndef __SENSORS_REGISTER_ADDRESSES_H__ +#define __SENSORS_REGISTER_ADDRESSES_H__ + +// $Id: sensors_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/sensors_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file sensors_register_addresses.h +/// \brief Symbolic addresses for the SENSORS unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define SENSORS_CORE_PCB_BASE 0x10050000 +#define SENSORS_V0_OFFSET 0x00000000 +#define SENSORS_CORE_V0 0x10050000 +#define SENSORS_V1_OFFSET 0x00000001 +#define SENSORS_CORE_V1 0x10050001 +#define SENSORS_V2_OFFSET 0x00000002 +#define SENSORS_CORE_V2 0x10050002 +#define SENSORS_V3_OFFSET 0x00000003 +#define SENSORS_CORE_V3 0x10050003 +#define SENSORS_V5_OFFSET 0x00000005 +#define SENSORS_CORE_V5 0x10050005 +#define SENSORS_V6_OFFSET 0x00000006 +#define SENSORS_CORE_V6 0x10050006 +#define SENSORS_V7_OFFSET 0x00000007 +#define SENSORS_CORE_V7 0x10050007 +#define SENSORS_V8_OFFSET 0x00000008 +#define SENSORS_CORE_V8 0x10050008 +#define SENSORS_V9_OFFSET 0x00000009 +#define SENSORS_CORE_V9 0x10050009 +#define SENSORS_V10_OFFSET 0x0000000a +#define SENSORS_CORE_V10 0x1005000a +#define SENSORS_V11_OFFSET 0x0000000b +#define SENSORS_CORE_V11 0x1005000b +#define SENSORS_V12_OFFSET 0x0000000c +#define SENSORS_CORE_V12 0x1005000c +#define SENSORS_V13_OFFSET 0x0000000d +#define SENSORS_CORE_V13 0x1005000d + +#endif // __SENSORS_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/sramctl_firmware_registers.h b/src/ssx/pgp/registers/sramctl_firmware_registers.h new file mode 100755 index 0000000..c8a7c26 --- /dev/null +++ b/src/ssx/pgp/registers/sramctl_firmware_registers.h @@ -0,0 +1,211 @@ +#ifndef __SRAMCTL_FIRMWARE_REGISTERS_H__ +#define __SRAMCTL_FIRMWARE_REGISTERS_H__ + +// $Id: sramctl_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:24 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/sramctl_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file sramctl_firmware_registers.h +/// \brief C register structs for the SRAMCTL unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union sramctl_srbar { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t sram_region_qualifier : 2; + uint32_t reserved : 3; + uint32_t sram_bar_region : 8; + uint32_t _reserved0 : 19; +#else + uint32_t _reserved0 : 19; + uint32_t sram_bar_region : 8; + uint32_t reserved : 3; + uint32_t sram_region_qualifier : 2; +#endif // _BIG_ENDIAN + } fields; +} sramctl_srbar_t; + + + +typedef union sramctl_srmr { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t sram_enable_remap : 1; + uint32_t sram_arb_en_send_all_writes : 1; + uint32_t sram_disable_lfsr : 1; + uint32_t sram_lfsr_fairness_mask : 5; + uint32_t sram_error_inject_enable : 1; + uint32_t sram_ctl_trace_en : 1; + uint32_t sram_ctl_trace_sel : 1; + uint32_t reserved : 5; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t reserved : 5; + uint32_t sram_ctl_trace_sel : 1; + uint32_t sram_ctl_trace_en : 1; + uint32_t sram_error_inject_enable : 1; + uint32_t sram_lfsr_fairness_mask : 5; + uint32_t sram_disable_lfsr : 1; + uint32_t sram_arb_en_send_all_writes : 1; + uint32_t sram_enable_remap : 1; +#endif // _BIG_ENDIAN + } fields; +} sramctl_srmr_t; + + + +typedef union sramctl_srmap { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t reserved : 1; + uint32_t sram_remap_source : 12; + uint32_t _reserved0 : 1; + uint32_t reserved1 : 3; + uint32_t sram_remap_dest : 13; + uint32_t reserved2 : 2; +#else + uint32_t reserved2 : 2; + uint32_t sram_remap_dest : 13; + uint32_t reserved1 : 3; + uint32_t _reserved0 : 1; + uint32_t sram_remap_source : 12; + uint32_t reserved : 1; +#endif // _BIG_ENDIAN + } fields; +} sramctl_srmap_t; + + + +typedef union sramctl_srear { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t sram_error_address : 16; + uint32_t _reserved0 : 16; +#else + uint32_t _reserved0 : 16; + uint32_t sram_error_address : 16; +#endif // _BIG_ENDIAN + } fields; +} sramctl_srear_t; + + + +typedef union sramctl_srbv0 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t boot_vector_word0 : 32; +#else + uint32_t boot_vector_word0 : 32; +#endif // _BIG_ENDIAN + } fields; +} sramctl_srbv0_t; + + + +typedef union sramctl_srbv1 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t boot_vector_word1 : 32; +#else + uint32_t boot_vector_word1 : 32; +#endif // _BIG_ENDIAN + } fields; +} sramctl_srbv1_t; + + + +typedef union sramctl_srbv2 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t boot_vector_word2 : 32; +#else + uint32_t boot_vector_word2 : 32; +#endif // _BIG_ENDIAN + } fields; +} sramctl_srbv2_t; + + + +typedef union sramctl_srbv3 { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t boot_vector_word3 : 32; +#else + uint32_t boot_vector_word3 : 32; +#endif // _BIG_ENDIAN + } fields; +} sramctl_srbv3_t; + + + +typedef union sramctl_srchsw { + + uint32_t value; + struct { +#ifdef _BIG_ENDIAN + uint32_t chksw_wrfsm_dly_dis : 1; + uint32_t chksw_allow1_rd : 1; + uint32_t chksw_allow1_wr : 1; + uint32_t chksw_allow1_rdwr : 1; + uint32_t chksw_oci_parchk_dis : 1; + uint32_t chksw_tank_rddata_parchk_dis : 1; + uint32_t chksw_tank_sr_rderr_dis : 1; + uint32_t chksw_val_be_addr_chk_dis : 1; + uint32_t chksw_so_spare : 2; + uint32_t _reserved0 : 22; +#else + uint32_t _reserved0 : 22; + uint32_t chksw_so_spare : 2; + uint32_t chksw_val_be_addr_chk_dis : 1; + uint32_t chksw_tank_sr_rderr_dis : 1; + uint32_t chksw_tank_rddata_parchk_dis : 1; + uint32_t chksw_oci_parchk_dis : 1; + uint32_t chksw_allow1_rdwr : 1; + uint32_t chksw_allow1_wr : 1; + uint32_t chksw_allow1_rd : 1; + uint32_t chksw_wrfsm_dly_dis : 1; +#endif // _BIG_ENDIAN + } fields; +} sramctl_srchsw_t; + + +#endif // __ASSEMBLER__ +#endif // __SRAMCTL_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/sramctl_register_addresses.h b/src/ssx/pgp/registers/sramctl_register_addresses.h new file mode 100755 index 0000000..baec5d5 --- /dev/null +++ b/src/ssx/pgp/registers/sramctl_register_addresses.h @@ -0,0 +1,30 @@ +#ifndef __SRAMCTL_REGISTER_ADDRESSES_H__ +#define __SRAMCTL_REGISTER_ADDRESSES_H__ + +// $Id: sramctl_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/sramctl_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file sramctl_register_addresses.h +/// \brief Symbolic addresses for the SRAMCTL unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define SRAMCTL_OCI_BASE 0x40030000 +#define SRAMCTL_SRBAR 0x40030000 +#define SRAMCTL_SRMR 0x40030008 +#define SRAMCTL_SRMAP 0x40030010 +#define SRAMCTL_SREAR 0x40030018 +#define SRAMCTL_SRBV0 0x40030020 +#define SRAMCTL_SRBV1 0x40030028 +#define SRAMCTL_SRBV2 0x40030030 +#define SRAMCTL_SRBV3 0x40030038 +#define SRAMCTL_SRCHSW 0x40030040 + +#endif // __SRAMCTL_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/tod_firmware_registers.h b/src/ssx/pgp/registers/tod_firmware_registers.h new file mode 100755 index 0000000..7a700d7 --- /dev/null +++ b/src/ssx/pgp/registers/tod_firmware_registers.h @@ -0,0 +1,58 @@ +#ifndef __TOD_FIRMWARE_REGISTERS_H__ +#define __TOD_FIRMWARE_REGISTERS_H__ + +// $Id: tod_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:23 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/tod_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file tod_firmware_registers.h +/// \brief C register structs for the TOD unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union tod_value_reg { + + 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 tod_incrementer : 60; + uint64_t tod_wof : 4; +#else + uint64_t tod_wof : 4; + uint64_t tod_incrementer : 60; +#endif // _BIG_ENDIAN + } fields; +} tod_value_reg_t; + + +#endif // __ASSEMBLER__ +#endif // __TOD_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/tod_register_addresses.h b/src/ssx/pgp/registers/tod_register_addresses.h new file mode 100755 index 0000000..ac7d136 --- /dev/null +++ b/src/ssx/pgp/registers/tod_register_addresses.h @@ -0,0 +1,22 @@ +#ifndef __TOD_REGISTER_ADDRESSES_H__ +#define __TOD_REGISTER_ADDRESSES_H__ + +// $Id: tod_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/tod_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file tod_register_addresses.h +/// \brief Symbolic addresses for the TOD unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define TOD_PIB_BASE 0x00040000 +#define TOD_VALUE_REG 0x00040020 + +#endif // __TOD_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/registers/tpc_firmware_registers.h b/src/ssx/pgp/registers/tpc_firmware_registers.h new file mode 100644 index 0000000..62f1c42 --- /dev/null +++ b/src/ssx/pgp/registers/tpc_firmware_registers.h @@ -0,0 +1,213 @@ +#ifndef __TPC_FIRMWARE_REGISTERS_H__ +#define __TPC_FIRMWARE_REGISTERS_H__ + +// $Id: tpc_firmware_registers.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/tpc_firmware_registers.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file tpc_firmware_registers.h +/// \brief C register structs for the TPC unit + +// *** WARNING *** - This file is generated automatically, do not edit. + +#ifndef SIXTYFOUR_BIT_CONSTANT +#ifdef __ASSEMBLER__ +#define SIXTYFOUR_BIT_CONSTANT(x) x +#else +#define SIXTYFOUR_BIT_CONSTANT(x) x##ull +#endif +#endif + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + + + + +typedef union tpc_perv_gp3 { + + 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 tp_chiplet_chiplet_en_dc : 1; + uint64_t put_in_later0 : 25; + uint64_t tp_chiplet_fence_pcb_dc : 1; + uint64_t put_in_later1 : 37; +#else + uint64_t put_in_later1 : 37; + uint64_t tp_chiplet_fence_pcb_dc : 1; + uint64_t put_in_later0 : 25; + uint64_t tp_chiplet_chiplet_en_dc : 1; +#endif // _BIG_ENDIAN + } fields; +} tpc_perv_gp3_t; + + + +typedef union tpc_gp0 { + + 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 put_in_later0 : 40; + uint64_t tc_node_id_dc : 3; + uint64_t tc_chip_id_dc : 3; + uint64_t put_in_later1 : 18; +#else + uint64_t put_in_later1 : 18; + uint64_t tc_chip_id_dc : 3; + uint64_t tc_node_id_dc : 3; + uint64_t put_in_later0 : 40; +#endif // _BIG_ENDIAN + } fields; +} tpc_gp0_t; + + + +typedef union tpc_gp0_and { + + 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 put_in_later0 : 40; + uint64_t tc_node_id_dc : 3; + uint64_t tc_chip_id_dc : 3; + uint64_t put_in_later1 : 18; +#else + uint64_t put_in_later1 : 18; + uint64_t tc_chip_id_dc : 3; + uint64_t tc_node_id_dc : 3; + uint64_t put_in_later0 : 40; +#endif // _BIG_ENDIAN + } fields; +} tpc_gp0_and_t; + + + +typedef union tpc_gp0_or { + + 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 put_in_later0 : 40; + uint64_t tc_node_id_dc : 3; + uint64_t tc_chip_id_dc : 3; + uint64_t put_in_later1 : 18; +#else + uint64_t put_in_later1 : 18; + uint64_t tc_chip_id_dc : 3; + uint64_t tc_node_id_dc : 3; + uint64_t put_in_later0 : 40; +#endif // _BIG_ENDIAN + } fields; +} tpc_gp0_or_t; + + + +typedef union tpc_hpr2 { + + 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 hang_pulse_reg : 6; + uint64_t suppress_hang : 1; + uint64_t _reserved0 : 57; +#else + uint64_t _reserved0 : 57; + uint64_t suppress_hang : 1; + uint64_t hang_pulse_reg : 6; +#endif // _BIG_ENDIAN + } fields; +} tpc_hpr2_t; + + + +typedef union tpc_device_id { + + 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 cfam_id : 32; + uint64_t fuse_nx_allow_crypto : 1; + uint64_t fuse_vmx_crypto_dis : 1; + uint64_t fuse_fp_throttle_en : 1; + uint64_t reserved32 : 1; + uint64_t socket_id : 3; + uint64_t chippos_id : 1; + uint64_t _reserved0 : 24; +#else + uint64_t _reserved0 : 24; + uint64_t chippos_id : 1; + uint64_t socket_id : 3; + uint64_t reserved32 : 1; + uint64_t fuse_fp_throttle_en : 1; + uint64_t fuse_vmx_crypto_dis : 1; + uint64_t fuse_nx_allow_crypto : 1; + uint64_t cfam_id : 32; +#endif // _BIG_ENDIAN + } fields; +} tpc_device_id_t; + + +#endif // __ASSEMBLER__ +#endif // __TPC_FIRMWARE_REGISTERS_H__ + diff --git a/src/ssx/pgp/registers/tpc_register_addresses.h b/src/ssx/pgp/registers/tpc_register_addresses.h new file mode 100644 index 0000000..50c7e97 --- /dev/null +++ b/src/ssx/pgp/registers/tpc_register_addresses.h @@ -0,0 +1,30 @@ +#ifndef __TPC_REGISTER_ADDRESSES_H__ +#define __TPC_REGISTER_ADDRESSES_H__ + +// $Id: tpc_register_addresses.h,v 1.1.1.1 2013/12/11 21:03:24 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/registers/tpc_register_addresses.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file tpc_register_addresses.h +/// \brief Symbolic addresses for the TPC unit + +// *** WARNING *** - This file is generated automatically, do not edit. + + +#define TPC_PERVPIB_BASE 0x00050000 +#define TPC_PERV_GP3 0x0005001b +#define TPC_PIB_BASE 0x01000000 +#define TPC_GP0 0x01000000 +#define TPC_GP0_AND 0x01000004 +#define TPC_GP0_OR 0x01000005 +#define TPC_MISCPIB_BASE 0x010f0000 +#define TPC_HPR2 0x010f0022 +#define TPC_TPCHIP_BASE 0x000f0000 +#define TPC_DEVICE_ID 0x000f000f + +#endif // __TPC_REGISTER_ADDRESSES_H__ + diff --git a/src/ssx/pgp/ssx.mk b/src/ssx/pgp/ssx.mk new file mode 100755 index 0000000..348718d --- /dev/null +++ b/src/ssx/pgp/ssx.mk @@ -0,0 +1,424 @@ +# $Id: ssx.mk,v 1.2 2014/06/26 12:55:39 cmolsen Exp $ +# $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/ssx.mk,v $ +# Make header for PgP SSX builds +# +# The application may define the following variables to control the +# build process: +# +# APP_INCLUDES : Aplication-specific header search paths +# +# DEFS : A string of -D<symbol>[=<value>] to control compilation +# +# SSX : Default ..; The path to the SSX source code. +# The default is set for building the SSX +# subdirectories. +# +# SSX_THREAD_SUPPORT : (0/1, default 1); Compile SSX thread and +# semaphore suppprt +# +# SSX_TIMER_SUPPORT : (0/1, default 1); Compile SSX timer suppprt +# +# PPC405_MMU_SUPPORT : (0/1, default 1); Compile for PPC405 simple MMU protection +# +# SIMICS_ENVIRONMENT : (0/1, current default 0); Compile for Simics +# +# SIMICS_MAGIC_PANIC : (0/1, current default 0); Use Simics Magic +# breakpoint for SSX_PANIC() instead of PowerPC trap. +# Note that Simics does not model trap correctly in +# external debug mode. +# +# GCC-O-LEVEL : The optimization level passed to GCC (default -Os). May +# also be defined empty (GCC-O-LEVEL=) to disable +# optimization. This variable can also be used to pass +# any other non-default setting to GCC, e.g. +# make GCC-O-LEVEL="-Os -fno-branch-count-reg" +# +# GCC-TOOL-PREFIX : The full path (including executable file prefixes) to +# the GCC cross-development tools to use. The default is +# "ppcnf-mcp5-" +# +# CTEPATH : This variable defaults to the afs/awd CTE tool +# installation - The PORE binutils are stored there. If +# you are not in Austin be sure to define CTEPATH in +# your .profile. + +# >> gitprep +# Use fips tracepp +TRACEPP = /afs/austin/projects/esw/fips820/Builds/built/tools/x86/tracepp +export OCCROOT = $(dir $(lastword $(MAKEFILE_LIST)))../../ + +ifndef SIMICS_ENVIRONMENT +SIMICS_ENVIRONMENT=0 +endif +# << gitprep + +ifndef GCC-TOOL-PREFIX +# >> gitprep +# The new compiler for GNU builds +GCC-TOOL-PREFIX = powerpc64-unknown-linux-gnu- +endif + +ifndef HOST-PREFIX +HOST-PREFIX = x86_64-pc-linux-gnu- +endif + +JAIL = $(HOST-PREFIX)jail +CC_ASM = $(GCC-TOOL-PREFIX)gcc # Assembly still doesn't use tracepp +CC = $(TRACEPP) $(GCC-TOOL-PREFIX)gcc +AS = $(JAIL) /usr/bin/as +AR = $(JAIL) /usr/bin/ar +LD = $(GCC-TOOL-PREFIX)ld +OBJDUMP = $(GCC-TOOL-PREFIX)objdump +OBJCOPY = $(JAIL) /usr/bin/objcopy +CPP = $(JAIL) /usr/bin/cpp +# << gitprep + + +ifndef CTEPATH +$(warning The CTEPATH variable is not defined; Defaulting to /afs/awd) +CTEPATH = /afs/awd/projects/cte +endif + +PORE-AS = $(CTEPATH)/tools/porebinutils/prod/bin/pore-elf64-as +PORE-AS = $(CTEPATH)/tools/porebinutils/prod/bin/pore-elf64-as +PORE-LD = $(CTEPATH)/tools/porebinutils/prod/bin/pore-elf64-ld +PORE-OBJCOPY = $(CTEPATH)/tools/porebinutils/prod/bin/pore-elf64-objcopy + +ifeq "$(SSX)" "" +SSX = .. +endif + +ifeq "$(LIB)" "" +LIB = ../../lib +endif + +ifeq "$(SSX_TIMER_SUPPORT)" "" +SSX_TIMER_SUPPORT = 1 +endif + +ifeq "$(SSX_THREAD_SUPPORT)" "" +SSX_THREAD_SUPPORT = 1 +endif + +ifeq "$(PPC405_MMU_SUPPORT)" "" +PPC405_MMU_SUPPORT = 1 +endif + +ifeq "$(PGP_ASYNC_SUPPORT)" "" +PGP_ASYNC_SUPPORT = 1 +endif + +ifndef GCC-O-LEVEL +GCC-O-LEVEL = -Os +endif + +# >> gitprep +GCC-DEFS += -DSIMICS_ENVIRONMENT=$(SIMICS_ENVIRONMENT) +# << gitprep +GCC-DEFS += -DSSX_TIMER_SUPPORT=$(SSX_TIMER_SUPPORT) +GCC-DEFS += -DSSX_THREAD_SUPPORT=$(SSX_THREAD_SUPPORT) +GCC-DEFS += -DPPC405_MMU_SUPPORT=$(PPC405_MMU_SUPPORT) +DEFS += $(GCC-DEFS) -DPGAS_PPC=1 -DCONFIGURE_PTS_SLW=0 +PORE-DEFS += $(GCC-DEFS) + +############################################################################ + +INCLUDES += $(APP_INCLUDES) \ + -I$(SSX)/ssx -I$(SSX)/ppc32 -I$(SSX)/ppc405 \ + -I$(SSX)/pgp -I$(SSX)/pgp/registers \ + -I$(LIB) + +PIPE-CFLAGS = -pipe -Wa,-m405 + +# >> gitprep +# Update compile flags for GNU build, allow warnings +GCC-CFLAGS += -g -Wall -fsigned-char -msoft-float \ + -m32 -mcpu=405 -mmultiple -mstring \ + -meabi -msdata=eabi -ffreestanding -fno-common \ + -fno-inline-functions-called-once +# << gitprep + +CFLAGS = -c $(GCC-CFLAGS) $(PIPE-CFLAGS) $(GCC-O-LEVEL) $(INCLUDES) +PORE-CFLAGS = -E $(GCC-CFLAGS) $(OPT) $(INCLUDES) +# >> gitprep +# Add compile flags needed for the GNU build +CPPFLAGS += -m32 -mcpu=405 -msdata=eabi -meabi -mstring -mmultiple +# << gitprep + +############################################################################ + +# Build object code +# +# %.o: %.c - Compile C code +# +# %.o: %.S - Compile PowerPC assembler (including PGAS-PPC assembly) + +%.o: %.c + $(CC) $(CFLAGS) $(DEFS) -o $@ $< + +%.o: %.S + $(CC_ASM) $(CFLAGS) $(DEFS) -o $@ $< + +#Temporary always use PGAS PPC Assembler for compiling .pS files. +#relocatable symbols are being added to the GPE (.pS) files and +#so need new way to compile using GNU assembler. +PGAS_PPC=1 + +# use "make PGAS_PPC=1" to compile .pS file using PGAS PPC assembler. +# If PGAS_PPC=1 is not part of the make command, then GNU assembler is +# used for compiling .pS files. +ifdef PGAS_PPC + +ifneq ($(MAKE_PORE_HOOKS),) + +# This Makefile included here defines how to convert *.pS into both the object +# file and the hooks object file. + +include $(MAKE_PORE_HOOKS) + +else + +%.o: %.pS +# >> gitprep +# Force use of PORE assembler for GNU builds +# $(CC_ASM) -x assembler-with-cpp $(CFLAGS) $(DEFS) -o $@ $< + $(CC_ASM) -x assembler-with-cpp $(PORE-CFLAGS) $(PORE-DEFS) $< | $(PORE-AS) - -o $@ +# << gitprep +endif + +%.lst: %.pS + $(CC_ASM) -x assembler-with-cpp $(CFLAGS) $(DEFS) \ + -Wa,-al -Wa,--listing-cont-lines=20 $< > $@ + +else +%.o: %.pS + $(CPP_ASM) -x assembler-with-cpp $(PORE-CFLAGS) $(PORE-DEFS) $< | $(PORE-AS) - -o $@ +endif + +# Other useful targets +# +# %.S: %.c - See what the assembler produces from the C code, however you can +# also just look at the final disassembly. +# +# %.lst: %.S - Get an assembler listing +# +# %.cpp: %.S - Preprocess PowerPC assembler source to stdout +# +# %.cpp: %.pS - Preprocess PORE assembler source to stdout +# +# %.cpp: %.c - Preprocess C source to stdout + +%.S: %.c + $(CC) $(CFLAGS) $(DEFS) -S -o $@ $< + +%.lst: %.S + $(CC_ASM) $(CFLAGS) $(DEFS) -Wa,-al -Wa,--listing-cont-lines=20 $< > $@ + +%.cpp: %.S + $(CC_ASM) $(CFLAGS) $(DEFS) -E $< + +%.cpp: %.pS + $(CC) -x assembler-with-cpp $(CFLAGS) $(DEFS) -E $< + +%.cpp: %.c + $(CC) $(CFLAGS) $(DEFS) -E $< + +# From the GNU 'Make' manual - these scripts uses the preprocessor to +# create dependency files (*.d), then mungs them slightly to make them +# work as Make targets. The *.d files are include-ed in the +# subdirectory Makefiles. + +%.d: %.c + @set -e; rm -f $@; \ + $(CC_ASM) -MM $(INCLUDES) $(CPPFLAGS) $(DEFS) $< > $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ + +%.d: %.S + @set -e; rm -f $@; \ + $(CC_ASM) -MM $(INCLUDES) $(CPPFLAGS) $(DEFS) $< > $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ + +%.d: %.pS + @set -e; rm -f $@; \ + $(CC_ASM) -MM $(INCLUDES) $(CPPFLAGS) -x assembler-with-cpp $(DEFS) $< > $@.$$$$; \ + sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ + rm -f $@.$$$$ + +############################################################################ +# +# GCC Compiler flags used in these builds. Comments, or reasons for +# non-obvious choices appear in [] after the GCC documentation. +# +#`-Os' +# Optimize for size. `-Os' enables all `-O2' optimizations that do +# not typically increase code size. It also performs further +# optimizations designed to reduce code size. +# +# `-Os' disables the following optimization flags: +# -falign-functions -falign-jumps -falign-loops +# -falign-labels -freorder-blocks -freorder-blocks-and-partition +# -fprefetch-loop-arrays -ftree-vect-loop-version +# +# If you use multiple `-O' options, with or without level numbers, +# the last such option is the one that is effective. +# +#`-g' +# Produce debugging information in the operating system's native +# format (stabs, COFF, XCOFF, or DWARF 2). GDB can work with this +# debugging information. +# +# On most systems that use stabs format, `-g' enables use of extra +# debugging information that only GDB can use; this extra information +# makes debugging work better in GDB but will probably make other +# debuggers crash or refuse to read the program. If you want to +# control for certain whether to generate the extra information, use +# `-gstabs+', `-gstabs', `-gxcoff+', `-gxcoff', or `-gvms' (see +# below). +# +# GCC allows you to use `-g' with `-O'. The shortcuts taken by +# optimized code may occasionally produce surprising results: some +# variables you declared may not exist at all; flow of control may +# briefly move where you did not expect it; some statements may not +# be executed because they compute constant results or their values +# were already at hand; some statements may execute in different +# places because they were moved out of loops. +# +# Nevertheless it proves possible to debug optimized output. This +# makes it reasonable to use the optimizer for programs that might +# have bugs. +# +#`-Wall' +# Turns on all optional warnings which are desirable for normal code. +# At present this is `-Wcomment', `-Wtrigraphs', `-Wmultichar' and a +# warning about integer promotion causing a change of sign in `#if' +# expressions. Note that many of the preprocessor's warnings are on +# by default and have no options to control them. +# +#`-Werror' +# Make all warnings into errors. +# +#`-fsigned-char' +# Let the type `char' be signed, like `signed char'. +# +# Note that this is equivalent to `-fno-unsigned-char', which is the +# negative form of `-funsigned-char'. Likewise, the option +# `-fno-signed-char' is equivalent to `-funsigned-char'. +# +#`-msoft-float' +# Generate output containing library calls for floating point. +# *Warning:* the requisite libraries are not available for all ARM +# targets. Normally the facilities of the machine's usual C +# compiler are used, but this cannot be done directly in +# cross-compilation. You must make your own arrangements to provide +# suitable library functions for cross-compilation. +# +# `-msoft-float' changes the calling convention in the output file; +# therefore, it is only useful if you compile _all_ of a program with +# this option. In particular, you need to compile `libgcc.a', the +# library that comes with GCC, with `-msoft-float' in order for this +# to work. +# +#`-pipe' +# Use pipes rather than temporary files for communication between the +# various stages of compilation. This fails to work on some systems +# where the assembler is unable to read from a pipe; but the GNU +# assembler has no trouble. +# +#`-mmultiple' +#`-mno-multiple' +# Generate code that uses (does not use) the load multiple word +# instructions and the store multiple word instructions. These +# instructions are generated by default on POWER systems, and not +# generated on PowerPC systems. Do not use `-mmultiple' on little +# endian PowerPC systems, since those instructions do not work when +# the processor is in little endian mode. The exceptions are PPC740 +# and PPC750 which permit the instructions usage in little endian +# mode. +# +#`-mstring' +#`-mno-string' +# Generate code that uses (does not use) the load string instructions +# and the store string word instructions to save multiple registers +# and do small block moves. These instructions are generated by +# default on POWER systems, and not generated on PowerPC systems. +# Do not use `-mstring' on little endian PowerPC systems, since those +# instructions do not work when the processor is in little endian +# mode. The exceptions are PPC740 and PPC750 which permit the +# instructions usage in little endian mode. +# +#`-meabi' +#`-mno-eabi' +# On System V.4 and embedded PowerPC systems do (do not) adhere to +# the Embedded Applications Binary Interface (eabi) which is a set of +# modifications to the System V.4 specifications. Selecting `-meabi' +# means that the stack is aligned to an 8 byte boundary, a function +# `__eabi' is called to from `main' to set up the eabi environment, +# and the `-msdata' option can use both `r2' and `r13' to point to +# two separate small data areas. Selecting `-mno-eabi' means that +# the stack is aligned to a 16 byte boundary, do not call an +# initialization function from `main', and the `-msdata' option will +# only use `r13' to point to a single small data area. The `-meabi' +# option is on by default if you configured GCC using one of the +# `powerpc*-*-eabi*' options. +# +# [We elected to use the EABI to reduce stack requirements and possibly reduce +# code size and improve performance. In practice it probably has little real +# effect since the code size and performance improvements only apply to global +# variables <= 8 bytes, and our applications will not have deeply nested call +# trees. Still, much of the assembler code requires/assumes the EABI is in +# place, and it certainly doesn't hurt anything to use it.] +# +#`-msdata=eabi' +# On System V.4 and embedded PowerPC systems, put small initialized +# `const' global and static data in the `.sdata2' section, which is +# pointed to by register `r2'. Put small initialized non-`const' +# global and static data in the `.sdata' section, which is pointed +# to by register `r13'. Put small uninitialized global and static +# data in the `.sbss' section, which is adjacent to the `.sdata' +# section. The `-msdata=eabi' option is incompatible with the +# `-mrelocatable' option. The `-msdata=eabi' option also sets the +# `-memb' option. +# +#`-memb' +# On embedded PowerPC systems, set the PPC_EMB bit in the ELF flags +# header to indicate that `eabi' extended relocations are used. +# +#`-ffreestanding' +# Assert that compilation takes place in a freestanding environment. +# This implies `-fno-builtin'. A freestanding environment is one +# in which the standard library may not exist, and program startup +# may not necessarily be at `main'. The most obvious example is an +# OS kernel. This is equivalent to `-fno-hosted'. +# +#`-fno-common' +# In C, allocate even uninitialized global variables in the data +# section of the object file, rather than generating them as common +# blocks. This has the effect that if the same variable is declared +# (without `extern') in two different compilations, you will get an +# error when you link them. The only reason this might be useful is +# if you wish to verify that the program will work on other systems +# which always work this way. +# +# [It is always assumed to be an error if two C source files declare global +# variables of the same name, since it is not clear whether this was intended +# or not.] +# +#`-finline-functions-called-once' +#`-fno-inline-functions-called-once' +# Consider all `static' functions called once for inlining into their +# caller even if they are not marked `inline'. If a call to a given +# function is integrated, then the function is not output as +# assembler code in its own right. +# +# Enabled if `-funit-at-a-time' is enabled. +# +# [There is a 'bug' in GCC related to inlining static, called-once +# functions. GCC allocates stack space in the caller for the stacks of ALL +# inlined functions of this type, even if they are called sequentially, +# leading in some cases to kilobytes of wasted stack space. If you want to +# inline a static called-once function you will need to explicity declare it +# as 'inline'.] + + diff --git a/src/ssx/pgp/ssx_port.h b/src/ssx/pgp/ssx_port.h new file mode 100755 index 0000000..613ac43 --- /dev/null +++ b/src/ssx/pgp/ssx_port.h @@ -0,0 +1,19 @@ +#ifndef __SSX_PORT_H__ +#define __SSX_PORT_H__ + +// $Id: ssx_port.h,v 1.1.1.1 2013/12/11 21:03:22 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/ssx_port.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_port.h +/// \brief The top-level PGP environment header for SSX. + +#define CHIP_PGP + +#include "ppc405.h" + +#endif /* __SSX_PORT_H__ */ diff --git a/src/ssx/pgp/ssxpgpfiles.mk b/src/ssx/pgp/ssxpgpfiles.mk new file mode 100755 index 0000000..dd12da1 --- /dev/null +++ b/src/ssx/pgp/ssxpgpfiles.mk @@ -0,0 +1,37 @@ +# $Id: ssxpgpfiles.mk,v 1.4 2014/06/26 12:56:28 cmolsen Exp $ +# $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/pgp/ssxpgpfiles.mk,v $ +# @file ssxpgpfiles.mk +# +# @brief mk for including pgp object files +# +# @page ChangeLogs Change Logs +# @section ssxpgpfiles.mk +# @verbatim +# +# +# Change Log ****************************************************************** +# Flag Defect/Feature User Date Description +# ------ -------------- ---------- ------------ ----------- +# @pb00E pbavari 03/11/2012 Makefile ODE support +# +# @endverbatim +# +########################################################################## +# Object Files +########################################################################## +PGP-C-SOURCES = pgp_init.c pgp_irq_init.c pgp_pmc.c pgp_ocb.c pgp_pba.c \ + pgp_id.c pgp_centaur.c +PGP-S-SOURCES = pgp_cache.S + +PGP-TIMER-C-SOURCES = +PGP-TIMER-S-SOURCES = + +PGP-THREAD-C-SOURCES = +PGP-THREAD-S-SOURCES = + +PGP-ASYNC-C-SOURCES = pgp_async.c pgp_async_pore.c pgp_async_ocb.c \ + pgp_async_pba.c +PGP-ASYNC-S-SOURCES = + +PGP_OBJECTS += $(PGP-C-SOURCES:.c=.o) $(PGP-S-SOURCES:.S=.o) + diff --git a/src/ssx/ppc32/Makefile b/src/ssx/ppc32/Makefile new file mode 100755 index 0000000..920144e --- /dev/null +++ b/src/ssx/ppc32/Makefile @@ -0,0 +1,33 @@ +# $Id: Makefile,v 1.2 2013/12/12 16:12:37 bcbrock Exp $ + +# This Makefile is designed to be invoked with the -I argument set to +# the location of the "ssx.mk" for the build. +# +# This makefile creates the libppc32.a library. + +# >> gitprep +# Path cleanup for GNU builds +SSX = .. +PGP = $(SSX)/pgp + +include $(PGP)/ssx.mk +# << gitprep +include ssxppc32files.mk + + + +libppc32.a: ${PPC32_OBJECTS} + $(AR) crs libppc32.a ${PPC32_OBJECTS} + +.PHONY : clean +clean: + rm -f *.o *.a *.d *.d.* + + +# This clause prevents the dependencies from creating errors during a clean. +# Whenever a header file is added or deleted it will likely be necessary to +# 'make clean' to force recomputation of dependencies. + +ifneq ($(MAKECMDGOALS),clean) +include $(PPC32_OBJECTS:.o=.d) +endif
\ No newline at end of file diff --git a/src/ssx/ppc32/div64.S b/src/ssx/ppc32/div64.S new file mode 100755 index 0000000..04ee008 --- /dev/null +++ b/src/ssx/ppc32/div64.S @@ -0,0 +1,255 @@ +// $Id: div64.S,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc32/div64.S,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file div64.S +/// \brief Unsigned 64/64 bit division +/// +/// This is IBM code, originally part of OS Open. The code has been slightly +/// modified from its original form, both to be compatible with SSX and to +/// change the function prototype slightly. +/// +/// The code was provided by Matt Tyrlik in Raleigh. + +/* @#START#@ +** +** PSCN (Power Service and Control Network) +** Cage Controller OS Open Code +** +** (C) Copyright International Business Machines Corporation 2002 +** All Rights Reserved +** Licensed Material - Program Property of I B M +** Refer to copyright instructions: Form G120-2083 +** +** Module: +** div64.s +** +** Description: +** Divide 64 bit unsigned values on 32 bit CPU +** div64(uint64_t dividen, uint64_t divisor, +** uint64_t *quotient, uint64_t *remainder) +** +** Original source from: +** "The PowerPC Compiler Writer's Guide", pp62-65 by +** Steve Hoxey, Faraydon Karim, Bill Hay, Hank Warray, +** published by Warthman Associates, 240 Hamilton Avenue, +** Palo Alto, CA 94301, USA, 1996 for IBM. +** ISBN 0-9649654-0-2. +** +** This version checks for divisor equal to zero. +** +** Environment: +** OS Open (XCOFF) +** +** Linkage: +** AIX 4.3.3 +** +** @author +** Thomas Richter +** +** History: +** Date Author Description +** ----------------------------------------------------------------------------- +** 23-Sep-02 Richter Created +** +** @#END#@*/ + + .nolist +#include "ssx.h" + .list + + .set r0, 0 + .set r1, 1 + .set r2, 2 + .set r3, 3 + .set r4, 4 + .set r5, 5 + .set r6, 6 + .set r7, 7 + .set r8, 8 + .set r9, 9 + .set r10, 10 + .set r11, 11 + .set r12, 12 + + .global_function __ppc32_udiv64 + + /* + ** Code comment notation: + ** msw = most-significant (high-order) word, i.e. bits 0..31 + ** lsw = least-significant (low-order) word, i.e. bits 32..63 + ** LZ = Leading Zeroes + ** SD = Significant Digits + ** + ** R3:R4 = Input parameter, dividend. + ** R5:R6 = Input parameter, divisor. + ** R7 = Output parameter, pointer to quotient. + ** R8 = Output parameter, pointer to remainder. + ** + ** Pointer arguments point to a uint64_t. + ** + ** Division is achieved using a shift/rotate/substract algorithsm + ** described above. + ** The registers are used as follows: + ** R3:R4 = dividend (upper 32bits:lower 32bits) + ** R5:R6 = divisor (upper 32bits:lower 32bits) + ** + ** R7:R8 = temporary 64 bit register (upper 32bits:lower 32bits) + ** count the number of leading 0s in the dividend + ** + ** Here is the description from the book. The dividend is placed + ** in the low order part of a 4 (32bit) register sequence named + ** tmp-high:tmp-low:dividend-high:dividend:low or tmp:dvd for short. + ** + ** Each iteration includes the following steps: + ** 1. Shift tmp:dvd by one bit to the left. + ** 2. Subtract the divisor from tmp. This is a 64 bit operation. + ** 3. If result is greater than or equal, place result in tmp and + ** set the low order bit of dividend + ** 4. If result is negative, do not modify tmp and + ** clear the low order bit of dividend + ** 5. If the number of iterations is less than the width of the + ** dividend, goto step 1. + ** + ** Now the algorithm can be improved by reducing the number of + ** iterations to be executed. + ** 1. Calculate the leading zeroes of the dividend. + ** 2. Calculate the leading zeroes of the divisor. + ** 3. Calculate the significant ones of the dividend. + ** 4. Calculate the significant ones of the divisor. + ** + ** Initial tmp := dvd >> (dvd.SD - dvs.SD) + ** Initial dvd := dvd << (dvd.LZ + dvs.SD) + ** Loops: dvd.SD - dvs.SD. + ** + ** Warning: Special care must be taken if dvd.LZ == dvs.LZ. The code + ** below does so by reducing the number of dvs.SD by one. This leads + ** to the loop being executed 1 more time than really necessary, + ** but avoids to check for the case when dvd.LZ == dvs.LZ. + ** This case (dvd.LZ == dvs.LZ) only checks for the number of leading + ** zeroes, but does not check if dividend is really greater than the + ** divisor. + ** Consider 16/17, both have an LZ value of 59. The code sets dvs.LZ + ** 60. This resutls in dvs.SD to 4, thus one iteration after which + ** tmp is the remainder 16. + */ + +__ppc32_udiv64: // SSX + /* Save result pointers on volatile spare registers */ + ori r12, r8, 0 /* Save remainder address */ + ori r11, r7, 0 /* Save quotient address */ + + /* count the number of leading 0s in the dividend */ + cmpwi cr0, r3, 0 /* dvd.msw == 0? */ + cntlzw r0, r3 /* R0 = dvd.msw.LZ */ + cntlzw r9, r4 /* R9 = dvd.lsw.LZ */ + bne cr0, lab1 /* if(dvd.msw == 0) dvd.LZ = dvd.msw.LZ */ + addi r0, r9, 32 /* dvd.LZ = dvd.lsw.LZ + 32 */ +lab1: + /* count the number of leading 0s in the divisor */ + cmpwi cr0, r5, 0 /* dvd.msw == 0? */ + cmpwi cr1, r6, 0 /* dvd.lsw == 0? */ + cntlzw r9, r5 /* R9 = dvs.msw.LZ */ + cntlzw r10, r6 /* R10 = dvs.lsw.LZ */ + bne cr0, lab2 /* if(dvs.msw == 0) dvs.LZ = dvs.msw.LZ */ + beq cr1, lab10 /* dvs.msw == 0 */ + addi r9, r10, 32 /* dvs.LZ = dvs.lsw.LZ + 32 */ + +lab2: + /* Determine shift amounts to minimize the number of iterations */ + cmpw cr0, r0, r9 /* Compare dvd.LZ to dvs.LZ */ + subfic r10, r0, 64 /* R10 = dvd.SD */ + bgt cr0, lab9 /* if(dvs > dvd) quotient = 0 */ + addi r9, r9, 1 /* See comment above. ++dvs.LZ (or --dvs.SD) */ + subfic r9, r9, 64 /* R9 = dvs.SD */ + add r0, r0, r9 /* (dvd.LZ + dvs.SD) = left shift of dvd for */ + /* initial dvd */ + subf r9, r9, r10 /* (dvd.SD - dvs.SD) = right shift of dvd for */ + /* initial tmp */ + mtctr r9 /* Number of iterations = dvd.SD - dvs.SD */ + + /* R7:R8 = R3:R4 >> R9 */ + cmpwi cr0, r9, 32 /* compare R9 to 32 */ + addi r7, r9, -32 + blt cr0, lab3 /* if(R9 < 32) jump to lab3 */ + srw r8, r3, r7 /* tmp.lsw = dvd.msw >> (R9 - 32) */ + addi r7, r0, 0 /* tmp.msw = 0 */ + b lab4 + +lab3: + srw r8, r4, r9 /* R8 = dvd.lsw >> R9 */ + subfic r7, r9, 32 + slw r7,r3,r7 /* R7 = dvd.msw << 32 - R9 */ + or r8, r8,r7 /* tmp.lsw = R8 | R7 */ + srw r7,r3,r9 /* tmp.msw = dvd.msw >> R9 */ +lab4: + /* R3:R4 = R3:R4 << R0 */ + cmpwi cr0, r0, 32 /* Compare R0 to 32 */ + addic r9, r0, -32 + blt cr0, lab5 /* if(R0 < 32) jump to lab5 */ + slw r3, r4, r9 /* dvd.msw = dvd.lsw << R9 */ + addi r4, r0, 0 /* dvd.lsw = 0 */ + b lab6 + +lab5: + slw r3, r3, r0 /* r3 = dvd.msw << r0 */ + subfic r9, r0, 32 + srw r9, r4, r9 /* r9 = dvd.lsw >> 32 - r0 */ + or r3, r3, r9 /* dvd.msw = r3 | r9 */ + slw r4, r4, r0 /* dvd.lsw = dvd.lsw << r0 */ +lab6: + /* Restoring division shift and subtract loop */ + addi r10, r0, -1 /* r10 = -1 */ + addic r7, r7, 0 /* Clear carry bit before loop starts */ +lab7: + /* + ** tmp:dvd is considered one large register + ** each portion is shifted left 1 bit by adding it to itself + ** adde sums the carry from the previous and creates a new carry + */ + adde r4, r4, r4 /* Shift dvd.lsw left 1 bit */ + adde r3, r3, r3 /* Shift dvd.msw to left 1 bit */ + adde r8, r8, r8 /* Shift tmp.lsw to left 1 bit */ + adde r7, r7, r7 /* Shift tmp.msw to left 1 bit */ + subfc r0, r6, r8 /* tmp.lsw - dvs.lsw */ + subfe. r9, r5, r7 /* tmp.msw - dvs.msw */ + blt cr0, lab8 /* if(result < 0) clear carry bit */ + or r8, r0, r0 /* Move lsw */ + or r7, r9, r9 /* Move msw */ + addic r0, r10, 1 /* Set carry bit */ + +lab8: + bdnz lab7 + + /* Write quotient and remainder */ + adde r4, r4, r4 /* quo.lsw (lsb = CA) */ + adde r3, r3, r3 /* quo.msw (lsb from lsw) */ + stw r4, 4(r11) + stw r3, 0(r11) + stw r8, 4(r12) /* rem.lsw */ + stw r7, 0(r12) /* rem.msw */ + blr + +lab9: + /* Qoutient is 0, divisor > dividend */ + addi r0, r0, 0 + stw r3, 0(r12) /* Store remainder */ + stw r4, 4(r12) + stw r0, 0(r11) /* Set quotient to zero */ + stw r0, 4(r11) + blr + +lab10: + /* Divisor is 0 */ + addi r0, r0, -1 + stw r0, 0(r12) /* Set remainder to zero */ + stw r0, 4(r12) + stw r0, 0(r11) /* Set quotient to zero */ + stw r0, 4(r11) + blr + + .epilogue __ppc32_udiv64 diff --git a/src/ssx/ppc32/gnu/stubs-32.h b/src/ssx/ppc32/gnu/stubs-32.h new file mode 100644 index 0000000..3da2fb2 --- /dev/null +++ b/src/ssx/ppc32/gnu/stubs-32.h @@ -0,0 +1,21 @@ +/* This file is automatically generated. + It defines a symbol `__stub_FUNCTION' for each function + in the C library which is a stub, meaning it will fail + every time called, usually setting errno to ENOSYS. */ + +#ifdef _LIBC + #error Applications may not define the macro _LIBC +#endif + +#define __stub___kernel_rem_pio2l +#define __stub_chflags +#define __stub_fattach +#define __stub_fchflags +#define __stub_fdetach +#define __stub_gtty +#define __stub_lchmod +#define __stub_revoke +#define __stub_setlogin +#define __stub_sigreturn +#define __stub_sstk +#define __stub_stty diff --git a/src/ssx/ppc32/ppc32.h b/src/ssx/ppc32/ppc32.h new file mode 100755 index 0000000..e7f7bf8 --- /dev/null +++ b/src/ssx/ppc32/ppc32.h @@ -0,0 +1,171 @@ +#ifndef __PPC32_H__ +#define __PPC32_H__ + +// $Id: ppc32.h,v 1.2 2014/03/14 15:11:46 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc32/ppc32.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc32.h +/// \brief Generic 32-bit PowerPC header for SSX +/// +/// The synchronization macros defined here all create a compiler +/// memory barrier that will cause GCC to flush/invalidate all memory data +/// held in registers before the macro. This is consistent with other systems, +/// e.g., the PowerPC Linux kernel, and is the safest way to define these +/// macros. + + +#include "ppc32_asm.h" +#include "ppc32_gcc.h" + +// Condition register fields + +#define CR_LT(n) (0x80000000u >> (4 * (n))) +#define CR_GT(n) (0x40000000u >> (4 * (n))) +#define CR_EQ(n) (0x20000000u >> (4 * (n))) +#define CR_SO(n) (0x10000000u >> (4 * (n))) + + +#ifndef __ASSEMBLER__ + +#include "stdint.h" + +/// ssize_t is defined explictly rather than bringing in all of <unistd.h> +#ifndef __ssize_t_defined +#define __ssize_t_defined +typedef int ssize_t; +#endif + +/// A memory barrier +#define barrier() asm volatile ("" : : : "memory") + +/// Ensure In-order Execution of Input/Output +#define eieio() asm volatile ("eieio" : : : "memory") + +/// Memory barrier +#define sync() asm volatile ("sync" : : : "memory") + +/// Instruction barrier +#define isync() asm volatile ("isync" : : : "memory") + +/// CouNT Leading Zeros Word +#define cntlzw(x) \ +({uint32_t __x = (x); \ + uint32_t __lzw; \ + asm volatile ("cntlzw %0, %1" : "=r" (__lzw) : "r" (__x)); \ + __lzw;}) + +/// CouNT Leading Zeros : uint32_t +static inline int +cntlz32(uint32_t x) { + return cntlzw(x); +} + +/// CouNT Leading Zeros : uint64_t +static inline int +cntlz64(uint64_t x) { + if (x > 0xffffffff) { + return cntlz32(x >> 32); + } else { + return 32 + cntlz32(x); + } +} + + +/// 32-bit population count +static inline int +popcount32(uint32_t x) +{ + return __builtin_popcount(x); +} + + +/// 64-bit population count +static inline int +popcount64(uint64_t x) +{ + return __builtin_popcountll(x); +} + + +// NB: Normally we wouldn't like to force coercion inside a macro because it +// can mask programming errors, but for the MMIO macros the addresses are +// typically manifest constants or 32-bit unsigned integer expressions so we +// embed the coercion to avoid warnings. + +/// 8-bit MMIO Write +#define out8(addr, data) \ +do {*(volatile uint8_t *)(addr) = (data); eieio();} while(0) + +/// 8-bit MMIO Read +#define in8(addr) \ +({uint8_t __data = *(volatile uint8_t *)(addr); eieio(); __data;}) + +/// 16-bit MMIO Write +#define out16(addr, data) \ +do {*(volatile uint16_t *)(addr) = (data); eieio();} while(0) + +/// 16-bit MMIO Read +#define in16(addr) \ +({uint16_t __data = *(volatile uint16_t *)(addr); eieio(); __data;}) + +/// 32-bit MMIO Write +#define out32(addr, data) \ +do {*(volatile uint32_t *)(addr) = (data); eieio();} while(0) + +/// 32-bit MMIO Read +#define in32(addr) \ +({uint32_t __data = *(volatile uint32_t *)(addr); eieio(); __data;}) + +/// 64-bit MMIO Write +#define out64(addr, data) \ + do { \ + uint64_t __data = (data); \ + volatile uint32_t *__addr_hi = (uint32_t *)(addr); \ + volatile uint32_t *__addr_lo = __addr_hi + 1; \ + *__addr_hi = (__data >> 32); \ + eieio(); \ + *__addr_lo = (__data & 0xffffffff); \ + eieio(); \ + } while(0) + +/// 64-bit MMIO Read +#define in64(addr) \ + ({ \ + uint64_t __data; \ + volatile uint32_t *__addr_hi = (uint32_t *)(addr); \ + volatile uint32_t *__addr_lo = __addr_hi + 1; \ + __data = *__addr_hi; \ + eieio(); \ + __data = (__data << 32) | *__addr_lo; \ + eieio(); \ + __data;}) + +#endif /* __ASSEMBLER__ */ + + +#ifndef __ASSEMBLER__ + +/// Store revision information as a (global) string constant +#define REVISION_STRING(symbol, rev) const char* symbol = rev; + +#else // __ASSEMBLER__ + +/// Store revision information as a global string constant + .macro .revision_string, symbol:req, rev:req + .pushsection .rodata + .balign 4 + .global \symbol +\symbol\(): + .asciz "\rev" + .balign 4 + .popsection + .endm + +#endif // __ASSEMBLER__ + +#endif /* __PPC32_H__ */ diff --git a/src/ssx/ppc32/ppc32_asm.h b/src/ssx/ppc32/ppc32_asm.h new file mode 100755 index 0000000..0207c22 --- /dev/null +++ b/src/ssx/ppc32/ppc32_asm.h @@ -0,0 +1,408 @@ +#ifndef __PPC32_ASM_H__ +#define __PPC32_ASM_H__ + +// $Id: ppc32_asm.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc32/ppc32_asm.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc32_asm.h +/// \brief Generic assembler macros for 32-bit PowerPC + +// Doxygen is confused by assembler; the best I know how to make it +// work is to put all of the documentation at the beginning like below +// and effectively comment out the code using Doxygen cond/endcond. + +/// \page ppc32_asm Generic assembler macros for 32-bit PowerPC +/// +/// +/// \section _lxzi _l<w,h,b>zi - Load register and Zero from Immediate address +/// +/// These macros encapsulate the 2-instruction sequence required to +/// load from a 32-bit immediate address. +/// +/// \arg \c dreg A register to receive the load data. +/// \arg \c areg A register to hold the immediate address. This can \e +/// not be register 0. Note that if \a areg != \a dreg +/// then \a areg will contain the address at the end of +/// the macro sequence. +/// \arg \c addr A 32-bit immediate address, which may be either an +/// absolute or relocatable expression. +/// +/// Forms: +/// +/// \b _lbzi \a dreg, \a areg, \a addr - Load Byte and Zero from Immediate address \n +/// \b _lhzi \a dreg, \a areg, \a addr - Load Halfword and Zero from Immediate address \n +/// \b _lwzi \a dreg, \a areg, \a addr - Load Word and Zero from Immediate address \n +/// +/// +/// \section _stxi _st<w,h,b>i - STore register to Immediate address +/// +/// These macros encapsulate the 2-instruction sequence required to +/// store to a 32-bit immediate address. +/// +/// \arg \c dreg The register to store. +/// \arg \c areg A register to hold the immediate address. This can \e +/// not be register 0, and can not be the same as \a dreg. +/// Note that \a areg will contain the address at the end of +/// the macro sequence. +/// \arg \c addr A 32-bit immediate address, which may be either an +/// absolute or relocatable expression. +/// +/// Forms: +/// +/// \b _stbi \a dreg, \a areg, \a addr - STore Byte to Immediate address \n +/// \b _sthi \a dreg, \a areg, \a addr - STore Halfword to Immediate address \n +/// \b _stwi \a dreg, \a areg, \a addr - STore Word to Immediate address \n +/// +/// +/// \section _lstzsd _<l,st><w,h,b><z>sd - Load/STore register from/to Small Data area +/// +/// These macros encapulate the small data area relocations for access +/// to storage in the small data sections .sbss, .sdata, .sbss2 and +/// .sdata2. Use of these macros implies small data area support in +/// the compile environment (for variables shared between compiled and +/// assembled code) and initialization code that sets up the small data +/// area registers R13 (and optionally R2). +/// +/// The relocations generated by this macro will work for both SVR4 ABI +/// and EABI environments. In particular, for EABI environments +/// the link editor will insert offsets to either R13 or R2 depending +/// on the section of the symbol. +/// +/// \arg \c dreg The register to load or store. +/// \arg \c addr A 32-bit immediate address, assumed to be a +/// relocatable address in one of the small data sections. +/// +/// Forms: +/// +/// \b _lbzsd \a dreg, \a addr - Load Byte and Zero from Small Data area \n +/// \b _lhzsd \a dreg, \a addr - Load Halfword and Zero from Small Data area \n +/// \b _lwzsd \a dreg, \a addr - Load Word and Zero from Small Data area \n +/// \b _stbsd \a dreg, \a addr - STore Byte to Small Data area \n +/// \b _sthsd \a dreg, \a addr - STore Halfword to Small Data area \n +/// \b _stwsd \a dreg, \a addr - STore Word to Small Data area \n +/// +/// +/// \section _liw _liw<a> - Load Immediate Word (Absolute) +/// +/// These macros encapsulate the two instructions required to load a +/// 32-bit immediate value into a register. If the immediate is an +/// absolute expression, then the \c 'a' form may be able to optimize +/// to a single instruction depending on whether only the high- or +/// low-order bits of the immediate are non-zero. +/// +/// Forms: +/// +/// \b _liw \a rd, \a imm - Load register \a rd with the 32-bit immediate \a imm \n +/// \b _liwa \a rd, \a imm - Load register \a rd with the 32-bit absolute immediate \a imm \n +/// +/// +/// \section _oriwa _oriwa - OR Immediate Word Absolute +/// +/// This macro encapsulates the logical OR of a 32-bit immediate with a +/// register. The immediate value must be an absolute expression. +/// +/// The PowerPC has instructions for OR-ing 16-bit immediates into the +/// upper (\c oris) and lower (\c ori) portions of a register. This +/// macro optimizes the generated code based on which bits (if any) of +/// the absolte immediate are non-zero. +/// +/// This special macro is only provided for the OR function. For other +/// logical operations and recording forms it is necessary in general +/// to first load the 32-bit immediate into a register (e.g., with \c +/// _liwa) then perform the logical operation. +/// +/// \arg \c rd The destination register; at the end will contain \c rs +/// OR \a imm +/// \arg \c rs The source register. +/// \arg \c imm 32-bit absolute expression. +/// +/// Forms: +/// +/// \b _oriwa \a rd, \a rs, \a imm - \a rd gets \a rs OR \a imm \n +/// +/// +/// \section _incr64_fast - 64-bit increment for fast interrupt handlers +/// +/// This macros implements 64-bit counter update in fast interrupt handlers +/// which are forbidden from using the carry-bit in the XER (without +/// saving/restoring it.) +/// +/// \arg \c rs Scratch register +/// \arg \c ra Register containing the counter address at entry +/// +/// \a rs and \a ra must be unique. At the end of the macro the count +/// is updated to memory and \a ra is unmodified. +/// +/// +/// \section _setclear_bits Set/Clear/Copy Bits from Immediate Positions +/// +/// There are situations where it is easier/faster to clear individual bits +/// and bit fields, set bits or copy fields, based on immediate bit numbers +/// and locations, rather than loading masks, since setting up a mask +/// requires 2 instruction in general, whereas these macros generate a single +/// instruction. +/// +/// \arg \c rd - The destination register +/// \arg \c rs - The source register +/// \arg \c n - An immediate size of a bit field, in the range 0 to 32 +/// \arg \c b - An immediate big-endian bit number in the range 0 to 31 +/// +/// Forms: +/// +/// \b _clrfield \a rd, \a rs, \a n, \a b - Clear an \a n bit field from \a rs +/// to \a rd starting from bit \a b \n +/// \b _clrbit \a rd, \a rs, \a b - Clear bit \a b \n +/// \b _setbit \a rd, \a rs, \a b - Set bit \a b \n +/// \b _copyfield \a rd, \a rs, \a n, \a b - Copy an n-bit field from \a rs to +/// \a rd starting from bit \a b \n +/// +/// +/// \section pseudo_ops Assembler Pseudo-Ops Macros +/// +/// Several macros define new 'pseudo-ops'. +/// +/// \subsection cache_align .cache_align +/// +/// The \c .cache_align pseudo-op is used to force alignment on a +/// cache-line boundary. It requires a preprocessor symbol definition for +/// \c LOG_CACHE_LINE_SIZE +/// +/// Forms: +/// +/// \b .cache_align \n +/// +/// +/// \subsection global_function Local and Global Functions +/// +/// The \c .function and \c .global_function pseudo-ops define function +/// symbols in the \c .text section. +/// +/// Forms: +/// +/// \b .function \a symbol - Define a local function \a symbol \n +/// \b .global_function \a symbol - Define a global function \a symbol \n +/// +/// +/// \subsection epilogue .epilogue +/// +/// The \c .epilogue pseudo-op adds size and type information for +/// functions defined in assembler. +/// +/// \arg \c symbol - Assembler epilogue for the function \a symbol. +/// +/// Forms: +/// +/// \b .epilogue \a symbol \n +/// +/// +/// \cond + +#ifdef __ASSEMBLER__ + +### **************************************************************************** +### _l<b,h,w>zi +### _st<b,h,w>i +### **************************************************************************** + + .macro _lbzi dreg, areg, addr + lis \areg, \addr@ha + .ifc \areg, \dreg + lbz \dreg, \addr@l(\areg) + .else + lbzu \dreg, \addr@l(\areg) + .endif + .endm + + .macro _lhzi dreg, areg, addr + lis \areg, \addr@ha + .ifc \areg, \dreg + lhz \dreg, \addr@l(\areg) + .else + lhzu \dreg, \addr@l(\areg) + .endif + .endm + + .macro _lwzi dreg, areg, addr + lis \areg, \addr@ha + .ifc \areg, \dreg + lwz \dreg, \addr@l(\areg) + .else + lwzu \dreg, \addr@l(\areg) + .endif + .endm + + .macro _stbi dreg, areg, addr + .ifc \areg, \dreg + .err + .endif + lis \areg, \addr@ha + stbu \dreg, \addr@l(\areg) + .endm + + .macro _sthi dreg, areg, addr + .ifc \areg, \dreg + .err + .endif + lis \areg, \addr@ha + sthu \dreg, \addr@l(\areg) + .endm + + .macro _stwi dreg, areg, addr + .ifc \areg, \dreg + .err + .endif + lis \areg, \addr@ha + stwu \dreg, \addr@l(\areg) + .endm + + +### **************************************************************************** +### _l<b,h,w>zsd +### _st<b,h,w>sd +### **************************************************************************** + + .macro _lbzsd dreg, addr + lbz \dreg, \addr@sda21(0) + .endm + + .macro _lhzsd dreg, addr + lhz \dreg, \addr@sda21(0) + .endm + + .macro _lwzsd dreg, addr + lwz \dreg, \addr@sda21(0) + .endm + + .macro _stbsd dreg, addr + stb \dreg, \addr@sda21(0) + .endm + + .macro _sthsd dreg, addr + sth \dreg, \addr@sda21(0) + .endm + + .macro _stwsd dreg, addr + stw \dreg, \addr@sda21(0) + .endm + + +### **************************************************************************** +### _liw<a> +### _oriwa +### **************************************************************************** + + .macro _liw rd, imm + lis \rd, \imm@h + ori \rd, \rd, \imm@l + .endm + + .macro _liwa rd, imm + .if (\imm & 0xffff0000) + lis \rd, \imm@h + .if (\imm & 0xffff) + ori \rd, \rd, \imm@l + .endif + .else + li \rd, \imm@l + .endif + .endm + + .macro _oriwa rd, rs, imm + .if (\imm & 0xffff0000) + oris \rd, \rs, \imm@h + .if (\imm & 0xffff) + ori \rd, \rd, \imm@l + .endif + .else + ori \rd, \rs, \imm@l + .endif + .endm + +### **************************************************************************** +### _incr64_fast +### **************************************************************************** + + .macro _incr64_fast, rs:req, ra:req + + lwz \rs, 4(\ra) + addi \rs, \rs, 1 + cmpwi \rs, 0 + stw \rs, 4(\ra) + bne 233643278f + + lwz \rs, 0(\ra) + addi \rs, \rs, 1 + stw \rs, 0(\ra) +233643278: + + .endm + +### **************************************************************************** +### _clrfield +### _clrbit +### _setbit +### _copyfield +### **************************************************************************** + + .macro _clrfield, rd, rs, n, b + rlwinm \rd, \rs, 0, (\b + \n) & 0x1f, (\b - 1) & 0x1f + .endm + + .macro _clrbit, rd, rs, b + _clrfield \rd, \rs, 1, \b + .endm + + .macro _setbit, rd, rs, b + .ifle \b - 15 + oris \rd, \rs, 1 << (15 - \b) + .else + ori \rd, \rs, 1 << (31 - \b) + .endif + .endm + + .macro _copyfield, rd, rs, n, b + rlwimi \rd, \rs, 0, \b , (\b + \n - 1) + .endm + +### **************************************************************************** +### .cache_align +### .<global_>function +### .epilogue +### **************************************************************************** + + .set _log_cache_line_size, LOG_CACHE_LINE_SIZE + + .macro .cache_align + .align _log_cache_line_size + .endm + + .macro .function symbol + .text + .align 2 + .endm + + .macro .global_function symbol + .text + .align 2 + .global \symbol + .endm + + .macro .epilogue symbol + .type \symbol, @function + .size \symbol, . - \symbol + .endm + +#endif /* __ASSEMBLER__ */ + +/// \endcond + +// Local Variables: +// mode:asm +// End: + +#endif /* __PPC32_ASM_H__ */ diff --git a/src/ssx/ppc32/ppc32_gcc.c b/src/ssx/ppc32/ppc32_gcc.c new file mode 100755 index 0000000..a00ab48 --- /dev/null +++ b/src/ssx/ppc32/ppc32_gcc.c @@ -0,0 +1,309 @@ +// $Id: ppc32_gcc.c,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc32/ppc32_gcc.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc32_gcc.h +/// \brief 32-bit PowerPC functions expected by GCC +/// +/// GCC expects certain built-in functions to be defined in the environment. +/// Since SSX applications are statically linked, we must define these +/// functions ourselves to avoid a static link with the GCC libraries, which +/// would legaly require us to distribute (at least) the binary forms of SSX +/// applications. +/// +/// We obviously had to look at some GCC library code to understand the +/// specifications of these routines. However, all of the code here is new - +/// no structure definitions or lines of executable code were copied from the +/// GCC sources. + +#include "ssx.h" +#include "ppc32_gcc.h" + +/// A 64-bit logical right shift. +/// +/// Note that shifts with negative shift counts or shifts with shift counts +/// longer than 63 bits are undefined. + +uint64_t +__lshrdi3(uint64_t x, int i) +{ + Uint64 input, result; + + if (i == 0) { + return x; + } + + input.value = x; + + if (i >= 32) { + result.word[0] = 0; + result.word[1] = input.word[0] >> (i - 32); + } else { + result.word[0] = input.word[0] >> i; + result.word[1] = (input.word[1] >> i) | (input.word[0] << (32 - i)); + } + + return result.value; +} + + +/// A 64 bit arithmetic left shift. +/// +/// Note that shifts with negative shift counts or shifts with shift counts +/// longer than 63 bits are undefined. + +uint64_t +__ashldi3(uint64_t x, int i) +{ + Uint64 input, result; + + if (i == 0) { + return x; + } + + input.value = x; + + if (i >= 32) { + result.word[1] = 0; + result.word[0] = input.word[1] << (i - 32); + } else { + result.word[1] = input.word[1] << i; + result.word[0] = (input.word[0] << i) | (input.word[1] >> (32 - i)); + } + + return result.value ; + +} + + +/// A 64 bit arithmetic right shift. +/// +/// Note that shifts with negative shift counts or shifts with shift counts +/// longer than 63 bits are undefined. + +uint64_t +__ashrdi3(uint64_t x, int i) +{ + Int64 input, result; + + if (i == 0) { + return x; + } + + input.value = x; + + if (i >= 32) { + result.word[0] = input.word[0] >> 31; + result.word[1] = input.word[0] >> (i - 32); + } else { + result.word[0] = input.word[0] >> i; + result.word[1] = + (((uint32_t)input.word[1]) >> i) | + (input.word[0] << (32 - i)); + } + + return result.value ; + +} + + +/// 32-bit Population count + +// This is a well-known divide-and-conquer algorithm, e.g. look on Wikipedia +// under "Hamming Weight". The idea is to compute sums of adjacent bit +// segments in parallel, in place. This compiles to 22 PPC405 instructions. + +int +__popcountsi2(uint32_t x) +{ + uint32_t m1 = 0x55555555; + uint32_t m2 = 0x33333333; + uint32_t m4 = 0x0f0f0f0f; + x -= (x >> 1) & m1; /* Sum pairs of bits */ + x = (x & m2) + ((x >> 2) & m2);/* Sum 4-bit segments */ + x = (x + (x >> 4)) & m4; /* Sum 8-bit segments */ + x += x >> 8; /* Sum 16-bit segments */ + return (x + (x >> 16)) & 0x3f; /* Final sum */ +} + + +/// 64-bit Population count + +int +__popcountdi2(uint64_t x) +{ + return __popcountsi2(x >> 32) + __popcountsi2(x & 0xffffffff); +} + + +// 64-bit divides +// +// For the unsigned case, note that divide by 0 returns quotient = remainder = +// 0. +// +// For the signed case, in general we perform the division on the absolute +// values and fix the signs of the quotient and remainder at the end. +// +// For the signed case, the convention in other libraries seems to be to +// ignore the case of the most-negative integer. Although it seems "wrong" to +// return the wrong answer when the right answer can be easily computed, in +// the interest of code size we follow the convention here and ignore the most +// negative integer. +// +// The assembler routine __ppc32_udiv64() assembles to 304 bytes. The full C +// routine __ppc_sdiv64 compiles to 416 bytes with the most-negative checks, +// but only 184 bytes as configured here. + +#if 0 +// For the signed cases, we need to handle the special case that the dividend +// or divisor is the most negative integer. +// +// If the dividend is the most negative integer, then dividing this integer by +// -1 would overflow as a positive quotient, so we set quotient and remainder +// to 0 in this case. For divide by 1, the quotient is the most negative +// integer. Otherwise we adjust the dividend by the absolute value of the +// divisor, then fix up the quotient later by adding or subtracting 1. +// +// If the divisor is the most negative integer, then the quotient is always 0 +// unless the dividend is also the most negative integer, in which case the +// quotient is 1 and the remainder is 0. +// +#endif + +uint64_t +__udivdi3(uint64_t u, uint64_t v) +{ + uint64_t quotient, remainder; + + __ppc32_udiv64(u, v, "ient, &remainder); + return quotient; +} + + +uint64_t +__umoddi3(uint64_t u, uint64_t v) +{ + uint64_t quotient, remainder; + + __ppc32_udiv64(u, v, "ient, &remainder); + return remainder; +} + + +#if 0 +#define INT64_T_MIN ((int64_t)(0x8000000000000000ull)) +#endif + +void +__ppc32_sdiv64(int64_t u, int64_t v, + int64_t *quotient, int64_t *remainder) +{ + int q_negate, r_negate; + uint64_t uu, uv; +#if 0 + int fixup = 0; +#endif + + q_negate = (u < 0) ^ (v < 0); + r_negate = (u < 0); + uu = (u < 0 ? -u : u); + uv = (v < 0 ? -v : v); + +#if 0 + if (u == INT64_T_MIN) { + if (v == -1) { + *quotient = 0; + *remainder = 0; + return; + } else if (v == 1) { + *quotient = INT64_T_MIN; + *remainder = 0; + return; + } else if (v == INT64_T_MIN) { + *quotient = 1; + *remainder = 0; + return; + } else { + fixup = 1; + u += (v < 0 ? -v : v); + } + } else if (v == INT64_T_MIN) { + *quotient = 0; + *remainder = u; + return; + } +#endif + + __ppc32_udiv64(uu, uv, (uint64_t *)quotient, (uint64_t *)remainder); + +#if 0 + if (fixup) { + *quotient += 1; + } +#endif + if (q_negate) { + *quotient = -(*quotient); + } + if (r_negate) { + *remainder = -(*remainder); + } +} + + +int64_t +__divdi3(int64_t u, int64_t v) +{ + int64_t quotient, remainder; + + __ppc32_sdiv64(u, v, "ient, &remainder); + return quotient; +} + + +int64_t +__moddi3(int64_t u, int64_t v) +{ + int64_t quotient, remainder; + + __ppc32_sdiv64(u, v, "ient, &remainder); + return remainder; +} + + +/// 64-bit unsigned compare as a function, returning 0 (<), 1 (==) or 2 (>). + +int +__ucmpdi2(uint64_t i_a, uint64_t i_b) +{ + Uint64 a, b; + int rv; + + a.value = i_a; + b.value = i_b; + + if (a.word[0] < b.word[0]) { + rv = 0; + } else if (a.word[0] > b.word[0]) { + rv = 2; + } else if (a.word[1] < b.word[1]) { + rv = 0; + } else if (a.word[1] > b.word[1]) { + rv = 2; + } else { + rv = 1; + } + + return rv; +} + + + + + + + + diff --git a/src/ssx/ppc32/ppc32_gcc.h b/src/ssx/ppc32/ppc32_gcc.h new file mode 100755 index 0000000..1925107 --- /dev/null +++ b/src/ssx/ppc32/ppc32_gcc.h @@ -0,0 +1,75 @@ +#ifndef __PPC32_GCC_H__ +#define __PPC32_GCC_H__ + +// $Id: ppc32_gcc.h,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc32/ppc32_gcc.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc32_gcc.h +/// \brief 32-bit PowerPC functions expected by GCC + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + +/// A 64-bit unsigned integer type + +typedef union { + uint64_t value; + uint32_t word[2]; +} Uint64; + +/// A 64-bit signed integer type + +typedef union { + int64_t value; + int32_t word[2]; +} Int64; + +uint64_t +__lshrdi3(uint64_t x, int i); + +uint64_t +__ashldi3(uint64_t x, int i); + +uint64_t +__ashrdi3(uint64_t x, int i); + +int +__popcountsi2(uint32_t x); + +int +__popcountdi2(uint64_t x); + +/// Unsigned 64/64 bit divide, returning quotient and remainder via pointers. + +void +__ppc32_udiv64(uint64_t u, uint64_t v, uint64_t *q, uint64_t *r); + +/// Signed 64/64 bit divide, returning quotient and remainder via pointers. + +void +__ppc32_sdiv64(int64_t u, int64_t v, int64_t *q, int64_t *r); + +uint64_t +__udivdi3(uint64_t u, uint64_t v); + +int64_t +__divdi3(int64_t u, int64_t v); + +int64_t +__moddi3(int64_t u, int64_t v); + +uint64_t +__umoddi3(uint64_t u, uint64_t v); + +int +__ucmpdi2(uint64_t a, uint64_t b); + +#endif /* __ASSEMBLER__ */ + +#endif /* __PPC32_GCC_H__ */ diff --git a/src/ssx/ppc32/savegpr.S b/src/ssx/ppc32/savegpr.S new file mode 100755 index 0000000..854f22b --- /dev/null +++ b/src/ssx/ppc32/savegpr.S @@ -0,0 +1,78 @@ +// $Id: savegpr.S,v 1.1.1.1 2013/12/11 21:03:25 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc32/savegpr.S,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// +/// \file savegpr.S +/// \brief Push registers onto or load registers from the stack +/// +/// This code was developed due to missing references to _savegpr_{X} +/// and _restgpr_{X}_x that surfaced when moving to GCC 4.5.1 and +/// using the -Os optimization level. +/// +/// The open-source code was viewed to get the spec, but no +/// code was copied. +/// + + + .macro SAVE reg + .global _savegpr_\reg + _savegpr_\reg\(): + stw \reg,(((31-\reg)*4 +4)*-1)(11) + .endm + + SAVE 14 + SAVE 15 + SAVE 16 + SAVE 17 + SAVE 18 + SAVE 19 + SAVE 20 + SAVE 21 + SAVE 22 + SAVE 23 + SAVE 24 + SAVE 25 + SAVE 26 + SAVE 27 + SAVE 28 + SAVE 29 + SAVE 30 + SAVE 31 + blr + + .macro RESTX reg + .global _restgpr_\reg\()_x + _restgpr_\reg\()_x: + .ifeq (31-\reg) + lwz 0,4(11) + .endif + lwz \reg,(((31-\reg)*4 +4)*-1)(11) + + .endm + + RESTX 14 + RESTX 15 + RESTX 16 + RESTX 17 + RESTX 18 + RESTX 19 + RESTX 20 + RESTX 21 + RESTX 22 + RESTX 23 + RESTX 24 + RESTX 25 + RESTX 26 + RESTX 27 + RESTX 28 + RESTX 29 + RESTX 30 + RESTX 31 + mtlr 0 + mr 1,11 + blr diff --git a/src/ssx/ppc32/ssxppc32files.mk b/src/ssx/ppc32/ssxppc32files.mk new file mode 100755 index 0000000..8697550 --- /dev/null +++ b/src/ssx/ppc32/ssxppc32files.mk @@ -0,0 +1,29 @@ +# $Id: ssxppc32files.mk,v 1.2 2014/06/26 12:58:31 cmolsen Exp $ +# $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc32/ssxppc32files.mk,v $ +# @file ssxppc32files.mk +# +# @brief mk for including ppc32 object files +# +# @page ChangeLogs Change Logs +# @section ssxppc32files.mk +# @verbatim +# +# +# Change Log ****************************************************************** +# Flag Defect/Feature User Date Description +# ------ -------------- ---------- ------------ ----------- +# @pb00E pbavari 03/11/2012 Makefile ODE support +# +# @endverbatim +# + +########################################################################## +# Object Files +########################################################################## +PPC32-C-SOURCES = ppc32_gcc.c +PPC32-S-SOURCES = div64.S savegpr.S + +PPC32_OBJECTS = $(PPC32-C-SOURCES:.c=.o) $(PPC32-S-SOURCES:.S=.o) + + + diff --git a/src/ssx/ppc405/Makefile b/src/ssx/ppc405/Makefile new file mode 100755 index 0000000..89c2c58 --- /dev/null +++ b/src/ssx/ppc405/Makefile @@ -0,0 +1,40 @@ +# $Id: Makefile,v 1.2 2013/12/12 16:12:38 bcbrock Exp $ + +# This Makefile is designed to be invoked with the -I argument set to +# the location of the "ssx.mk" for the build + +# >> gitprep +# Path cleanup for GNU builds +SSX = .. +PGP = $(SSX)/pgp + +include $(PGP)/ssx.mk +# << gitprep +include ssxppc405files.mk + +ifeq "$(SSX_TIMER_SUPPORT)" "1" +PPC405_OBJECTS += ${PPC405-TIMER-C-SOURCES:.c=.o} ${PPC405-TIMER-S-SOURCES:.S=.o} +endif + +ifeq "$(SSX_THREAD_SUPPORT)" "1" +PPC405_OBJECTS += ${PPC405-THREAD-C-SOURCES:.c=.o} ${PPC405-THREAD-S-SOURCES:.S=.o} +endif + +ifeq "$(PPC405_MMU_SUPPORT)" "1" +PPC405_OBJECTS += ${PPC405-MMU-C-SOURCES:.c=.o} ${PPC405-MMU-S-SOURCES:.S=.o} +endif + + +all: local + $(MAKE) -I ../pgp -C ../ppc32 + +local: $(PPC405_OBJECTS) + +.PHONY : clean +clean: + rm -f *.o *.d *.d.* + $(MAKE) -I ../pgp -C ../ppc32 clean + +ifneq ($(MAKECMDGOALS),clean) +include $(PPC405_OBJECTS:.o=.d) +endif
\ No newline at end of file diff --git a/src/ssx/ppc405/ppc405.h b/src/ssx/ppc405/ppc405.h new file mode 100755 index 0000000..18b0c53 --- /dev/null +++ b/src/ssx/ppc405/ppc405.h @@ -0,0 +1,771 @@ +#ifndef __PPC405_H__ +#define __PPC405_H__ + +// $Id: ppc405.h,v 1.3 2014/02/03 01:30:42 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405.h +/// \brief PowerPC 405 port header for SSX + +// The 405 has a 32-byte line and 2-way set associative caches. The cache +// configuration varies by chip/ASIC. +// +// Regarding the DCACHE_TAG_MASK, used by dcache_flush_all: The IBM +// documentation on the D-cache tag sizes doesn't make any sense to me - it +// claims the tag size is constant regardless of the size of the cache. +// However the Xilinx documentation for their 405 core (which has the same +// 16KB cache as PgP) is consistent with the way the DCACHE_TAG_MASK is +// defined here. + +#define CACHE_LINE_SIZE 32 +#define LOG_CACHE_LINE_SIZE 5 + +#define ICACHE_WAYS 2 +#define DCACHE_WAYS 2 + +#define LOG_ICACHE_WAYS 1 +#define LOG_DCACHE_WAYS 1 + +#define ICACHE_LINES (ICACHE_SIZE / CACHE_LINE_SIZE) +#define DCACHE_LINES (DCACHE_SIZE / CACHE_LINE_SIZE) + +#define DCACHE_TAG_MASK \ + ((0xffffffff << (LOG_DCACHE_SIZE - LOG_DCACHE_WAYS)) & 0xffffffff) + +#ifdef CHIP_PGP + +#define ICACHE_SIZE (16 * 1024) +#define DCACHE_SIZE (16 * 1024) + +#define LOG_ICACHE_SIZE 14 +#define LOG_DCACHE_SIZE 14 + +#else +#error "Please define the cache configuration of the processor" +#endif + +// Macros to define where declared code is actually compiled + +#ifdef __PPC405_C__ +#define IF__PPC405_CORE_C__(x) x +#define UNLESS__PPC405_CORE_C__(x) +#else +#define IF__PPC405_CORE_C__(x) +#define UNLESS__PPC405_CORE_C__(x) x +#endif + +#ifdef __PPC405_IRQ_CORE_C__ +#define IF__PPC405_IRQ_CORE_C__(x) x +#define UNLESS__PPC405_IRQ_CORE_C__(x) +#else +#define IF__PPC405_IRQ_CORE_C__(x) +#define UNLESS__PPC405_IRQ_CORE_C__(x) x +#endif + + +#ifdef CHIP_PGP +#include "pgp.h" +#endif + +#include "ppc32.h" +#include "ppc405_dcr.h" +#include "ppc405_spr.h" +#include "ppc405_msr.h" +#include "ppc405_irq.h" +#include "ppc405_cache.h" + +#if PPC405_MMU_SUPPORT + +#include "ppc405_mmu.h" + +#ifndef PPC405_IR_SUPPORT +#define PPC405_IR_SUPPORT 1 +#endif + +#ifndef PPC405_DR_SUPPORT +#define PPC405_DR_SUPPORT 1 +#endif + +#define PPC405_RELOCATION_MODE \ + ((PPC405_IR_SUPPORT * MSR_IR) | (PPC405_DR_SUPPORT * MSR_DR)) + +#ifndef __ASSEMBLER__ +void* +memcpy_real(void* dest, const void* src, size_t n); +#endif + +#else /* PPC405_MMU_SUPPORT */ + +#define PPC405_RELOCATION_MODE 0 + +#ifndef __ASSEMBLER__ +static inline void* +memcpy_real(void* dest, const void* src, size_t n) +{ + memcpy(dest, src, n); + icache_invalidate_all(); + return dest; +} +#endif + +#endif /* PPC405_MMU_SUPPORT */ + +/// By default, in MMU mode free space is read/write only, just like normal +/// data. Saome applications may need to execute from free space however, and +/// can override this default. + +#ifndef EXECUTABLE_FREE_SPACE +#define EXECUTABLE_FREE_SPACE 0 +#endif + +#include "ppc405_context.h" + +// PPC405 stack characteristics for SSX. The pre-pattern pattern is selected +// to be easily recognizable yet be an illegal instruction. + +#define SSX_STACK_DIRECTION -1 +#define SSX_STACK_PRE_DECREMENT 1 +#define SSX_STACK_ALIGNMENT 8 +#define SSX_STACK_TYPE unsigned int +#define SSX_STACK_PATTERN 0x03abcdef + +// Kernel data structure offsets for assembler code + +#define SSX_THREAD_OFFSET_SAVED_STACK_POINTER 0 +#define SSX_THREAD_OFFSET_STACK_LIMIT 4 +#define SSX_THREAD_OFFSET_STACK_BASE 8 + +// SSX boot loader panic codes + +#define PPC405_BOOT_CCR0_MODIFY_FAILED 0x00405000 +#define PPC405_BOOT_VECTORS_NOT_ALIGNED 0x00405001 + +// Interrupt handler panic codes + +#define PPC405_DEFAULT_IRQ_HANDLER 0x00405010 +#define PPC405_DEFAULT_SPECIAL_HANDLER 0x00405011 +#define PPC405_PHANTOM_INTERRUPT 0x00405012 +#define PPC405_PROGRAM_HALT 0x00405013 + + +// Exception handling invariant panic codes + +#define PPC405_IRQ_FULL_EXIT_INVARIANT 0x00405020 +#define PPC405_IRQ_FAST2FULL_INVARIANT 0x00405021 + + +// API error panic codes + +#define PPC405_CACHE_ALIGNMENT 0x00405030 + +// Application-overrideable definitions + +/// The default thread machine context has MSR[CE], MSR[EE] and MSR[ME] set, +/// and all other MSR bits cleared. +/// +/// The default definition allows critical, non-critical and machine check +/// exceptions. Debug interrupts are not enabled by default. This definition +/// can be overriden by the application. If MMU protection is enabled then +/// the IR/DR bits are also modeably set. + +#ifndef SSX_THREAD_MACHINE_CONTEXT_DEFAULT +#define SSX_THREAD_MACHINE_CONTEXT_DEFAULT \ + (MSR_CE | MSR_EE | MSR_ME | PPC405_RELOCATION_MODE) +#endif + + +#ifndef __ASSEMBLER__ + +/// The SSX kernel default panic sequence for C code +/// +/// By default a kernel panic from C code forces external debug mode then +/// generates a \c trap instruction followed by the error code. The \a code +/// argument must be a compile-time integer immediate. This definition can be +/// overriden by the application. +/// +/// The OCC may be running in internal debug mode for various reasons, and +/// TRAP-ing in internal debug mode would lead to an infinite loop in the +/// default Program Interrupt handler - which itself would be a TRAP (since +/// that's the default implementation of SSX_PANIC(). Therefore by default +/// the panic is implemented as a special code sequence that forces the core +/// into external debug mode before issuing a TRAP which will halt the core. +/// To preserve the state we use the special global variables +/// __ssx_panic_save_dbcr0 and __ssx_panic_save_r3 defined in ppc405_core.c. +/// The original value of DBCR0 is destroyed, but can be recovered from the +/// global. In the end %r3 is reloaded from temporary storage and will be +/// unchanged at the halt. +/// +/// Note that there is a small chance that an interrupt will fire and +/// interrupt this code before the halt - in general there is no way around +/// this. +/// +/// The Simics environment does not model Debug events correctly. It executes +/// the TRAP as an illegal instruction and branches to the Program Interrupt +/// handler, destroying the contents of SRR0 and SRR1. Therefore we always +/// insert a special Simics magic breakpoint (which is an effective NOP) +/// before the hardware trap. The special-form magic instruction is +/// recognized by our Simics support scripts which decode the kernel state and +/// try to help the user interpret what happened based on the TRAP code. + +#ifndef SSX_PANIC + +#define SSX_PANIC(code) \ + do { \ + barrier(); \ + asm volatile ("stw %r3, __ssx_panic_save_r3@sda21(0)"); \ + asm volatile ("mfdbcr0 %r3"); \ + asm volatile ("stw %r3, __ssx_panic_save_dbcr0@sda21(0)"); \ + asm volatile ("lwz %r3, __ssx_panic_dbcr0@sda21(0)"); \ + asm volatile ("mtdbcr0 %r3"); \ + asm volatile ("isync"); \ + asm volatile ("lwz %r3, __ssx_panic_save_r3@sda21(0)"); \ + asm volatile ("rlwimi 1,1,0,0,0"); \ + asm volatile ("trap"); \ + asm volatile (".long %0" : : "i" (code)); \ + } while (0) + +// These variables are used by the SSX_PANIC() definition above to save and +// restore state. __ssx_panic_dbcr0 is the value loaded into DBCR0 to force +// traps to halt the OCC and freeze the timers. + +#ifdef __PPC405_CORE_C__ +uint32_t __ssx_panic_save_r3; +uint32_t __ssx_panic_save_dbcr0; +uint32_t __ssx_panic_dbcr0 = DBCR0_EDM | DBCR0_TDE | DBCR0_FT; +#endif + +#endif // SSX_PANIC + +/// This is the Simics 'magic breakpoint' instruction. +/// +/// Note that this form does not include a memory barrier, as doing so might +/// change the semantics of the program. There is an alternative form +/// SIMICS_MAGIC_BREAKPOINT_BARRIER that does include a barrier. + +#define SIMICS_MAGIC_BREAKPOINT asm volatile ("rlwimi 0,0,0,0,0") + +/// This is the Simics 'magic breakpoint' instruction including a memory +/// barrier. +/// +/// Note that the memory barrier guarantees that all variables held in +/// registers are flushed to memory before the breakpoint, however this might +/// change the semantics of the program. There is an alternative form of +/// SIMICS_MAGIC_BREAKPOINT that does not include a barrier. If the idea is +/// to use the breakpoint for tracing code execution in Simics, the barrier +/// form may be preferred so that variable values will be visible in memory. + +#define SIMICS_MAGIC_BREAKPOINT_BARRIER \ + asm volatile ("rlwimi 0,0,0,0,0" : : : "memory") + + +#else // __ASSEMBLER__ + +/// This is the Simics 'magic breakpoint' instruction. An assembler macro +/// form is also provided for use within macros. + +#define SIMICS_MAGIC_BREAKPOINT rlwimi 0,0,0,0,0 + + .macro _simics_magic_breakpoint + rlwimi 0,0,0,0,0 + .endm + +/// The SSX kernel panic default panic sequence for assembler code +/// +/// By default a kernel panic from assembler forces external debug mode then +/// generates a \c trap instruction followed by the error code. The \a code +/// argument must be a compile-time integer immediate. This definition can be +/// overriden by the application. +/// +/// See the comments for the non-ASSEMBLER version for further details. Note +/// that the code space reserved for exception handlers is only 8 +/// instructions, so in the assembler context we don't save DBCR0 as doing so +/// would require 10. + +#ifndef SSX_PANIC + +#define SSX_PANIC(code) _ssx_panic code + + .macro _ssx_panic, code + _stwsd %r3, __ssx_panic_save_r3 + _lwzsd %r3, __ssx_panic_dbcr0 + mtdbcr0 %r3 + isync + _lwzsd %r3, __ssx_panic_save_r3 + rlwimi 1,1,0,0,0 + trap + .long \code + .endm + +#endif // SSX_PANIC + +#endif // __ASSEMBLER__ + + +// Application-overridible definitions for the SSX boot loader + +/// In order to enable the default kernel panic (a trap) to halt the machine, +/// the Debug Control Register 0 (DBCR0) is initialized in externel debug +/// mode, with the Trap Debug Event enabled so that the trap will not cause a +/// program exception, and the FT bit set so that the timers will freeze. +/// This definition can be overridden by the application. +/// +/// NB: It is expected that a reliable production system will redefine all of +/// the 'panic' macros and the default DBCR0 setup. + +#ifndef PPC405_DBCR0_INITIAL +#define PPC405_DBCR0_INITIAL (DBCR0_EDM | DBCR0_TDE | DBCR0_FT) +#endif + +/// This is the value of the MSR used during initialization. Once SSX threads +/// are started (with \c ssx_start_threads()), all machine contexts derive +/// from the default thread context \c +/// SSX_THREAD_MACHINE_CONTEXT_DEFAULT. This definition can be overriden by +/// the application. +/// +/// The default is to enable machine checks only. + +#ifndef PPC405_MSR_INITIAL +#define PPC405_MSR_INITIAL MSR_ME +#endif + +/// This is the initial value of Cache Control Register 0 (CCR0). This +/// definition can be overridden by the application. +/// +/// The default sets the CCR0 to give priority to DCU and ICU operations. The +/// user should consider setting other options in this register that affect +/// performance, e.g., ICU prefetching. Other options can be set at run time +/// with the API \c ppc405_ccr0_modify(). + +#ifndef PPC405_CCR0_INITIAL +#define PPC405_CCR0_INITIAL (CCR0_DPP1 | CCR0_IPP0 | CCR0_IPP1) +#endif + +/// The \a argc argument passed to \c main(). This definition can be overriden +/// by the application. + +#ifndef PPC405_ARGC_INITIAL +#define PPC405_ARGC_INITIAL 0 +#endif + +/// The \a argv argument passed to \c main(). This definition can be overriden +/// by the application. + +#ifndef PPC405_ARGV_INITIAL +#define PPC405_ARGV_INITIAL 0 +#endif + +/// Optionally trap the reset for the debugger, which means that the PPC405 +/// will simply spin at the symbol \c __reset_trap after a chip reset. Set R0 +/// to a non-zero value in the debugger to continue execution. This definition +/// can be overriden by the application. + +#ifndef PPC405_RESET_TRAP +#define PPC405_RESET_TRAP 0 +#endif + +#ifndef __ASSEMBLER__ + +/// The PPC405 SSX machine context is simply the MSR, a 32-bit integer. + +typedef uint32_t SsxMachineContext; + +/// Disable interrupts at the given priority level, and return the current +/// context. +/// +/// \param priority The interrupt priority level to disable, either \c +/// SSX_NONCRITICAL, \c SSX_CRITICAL or \c SSX_SUPERCRITICAL. For best +/// efficiency, the \a priority parameter should be a manifest constant. +/// +/// \param context A pointer to an SsxMachineContext, this is the context that +/// existed before interrupts were disabled. Typically this +/// context is restored at the end of a critical section. +/// +/// The PPC405 supports a 'super-critical' context in which every possible +/// maskable exception is disabled. +/// +/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_ARGUMENT_INTERRUPT An illegal priority was specified. + +UNLESS__PPC405_CORE_C__(extern) +inline int +ssx_interrupt_disable(int priority, SsxMachineContext *context) +{ + *context = mfmsr(); + + if (priority == SSX_NONCRITICAL) { + + wrteei(0); + + } else if (priority == SSX_CRITICAL) { + + mtmsr(*context & ~(MSR_EE | MSR_CE)); + + } else if (priority == SSX_SUPERCRITICAL) { + + mtmsr(*context & ~(MSR_APE | MSR_WE | MSR_CE | MSR_EE | MSR_ME | + MSR_DWE | MSR_DE)); + + } else if (SSX_ERROR_CHECK_API) { + SSX_ERROR(SSX_INVALID_ARGUMENT_INTERRUPT); + } + + return SSX_OK; +} + + +/// Set the machine context. +/// +/// \param context A pointer to an SsxMachineContext +/// +/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_ARGUMENT_CONTEXT_SET A null pointer was provided as +/// the \a context argument or an illegal machine context was specified. + +UNLESS__PPC405_CORE_C__(extern) +inline int +ssx_machine_context_set(SsxMachineContext *context) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(context == 0, SSX_INVALID_ARGUMENT_CONTEXT_SET); + } + + mtmsr(*context); + + return SSX_OK; +} + + +/// Get the machine context. +/// +/// \param context A pointer to an SsxMachineContext. +/// +/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_ARGUMENT_CONTEXT_GET A null pointer was provided as +/// the \a context argument. + +UNLESS__PPC405_CORE_C__(extern) +inline int +ssx_machine_context_get(SsxMachineContext *context) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(context == 0, SSX_INVALID_ARGUMENT_CONTEXT_GET); + } + + *context = mfmsr(); + + return SSX_OK; +} + + +/// The SSX kernel thread context switch - PPC405 uses the system call +/// exception. + +#define __ssx_switch() asm volatile ("sc") + + +/// In the PowerPC EABI all initial stack frames require 8 bytes - the 4 bytes +/// at the SP are zeroed to indicate the end of the stack, and the 4 bytes +/// behind the SP are for the initial subroutine's LR. + +static inline void +__ssx_stack_create_initial_frame(SsxAddress *stack, size_t *size) \ +{ + *stack -= 8; + *size -= 8; + *((SSX_STACK_TYPE *)(*stack)) = 0; +} + + +/// The SSX Kernel Context for PPC405 +/// +/// The SSX portable kernel does not define how the kernel keeps track of +/// whether SSX is running, interrupt levels, and other debug +/// information. Instead it defines an API that the port must provide to the +/// portable kernel. +/// +/// In the PPC405 port, the kernel context is maintained in USPRG0. This +/// 32-bit value is treated as 5 distinct fields as indicated in the structure +/// definition. For certain tests it's also helpful to look at the two +/// interrupt counters as a single 0/non-0 field. + +typedef union { + + uint32_t value; + + struct { + + /// The critical interrupt nesting level. If this field is non-zero, + /// then interrupt priority and preemption rules guarantee that a + /// critical interrupt handler is running, and the \c irq field will + /// contain the SsxIrqId of the currently active critical interrupt. + unsigned critical_interrupts : 8; + + /// The non-critical interrupt nesting level. If this field is + /// non-zero and the \c critical_interrupts field is 0, then interrupt + /// priority and preemption rules guarantee that a noncritical + /// interrupt handler is running, and the \c irq field will contain + /// the SsxIrqId of the currently active noncritical interrupt. + unsigned noncritical_interrupts : 8; + + /// The SsxIrqId of the currently running (or last run) handler. If + /// either of the interrupt nesting levels are non-0, then this is the + /// SsxIrqId of the IRQ that is currently executing. + unsigned irq : 8; + + /// A flag indicating that SSX is in thread mode after a call of + /// ssx_start_threads(). + unsigned thread_mode : 1; + + /// The priority of the currently running thread. In an interrupt + /// context, this is the priority of the thread that was interrupted. + unsigned thread_priority : 7; + + } fields; + + struct { + + /// Used as a 0/non-0 flag for interrupt context. + unsigned interrupt_context : 16; + + /// Ignore + unsigned ignore : 16; + + } merged_fields; + +} __SsxKernelContext; + + +// These APIs are provided to the SSX portable kernel by the port. + +/// SSX threads have been started by a call of ssx_start_threads(). + +#define __ssx_kernel_mode_thread() \ + ({ \ + __SsxKernelContext __ctx; \ + __ctx.value = mfspr(SPRN_USPRG0); \ + __ctx.fields.thread_mode;}) + + +/// SSX is executing in a thread context (not an interrupt handler). + +#define __ssx_kernel_context_thread() \ + ({ \ + __SsxKernelContext __ctx; \ + __ctx.value = mfspr(SPRN_USPRG0); \ + __ctx.fields.thread_mode && !__ctx.merged_fields.interrupt_context;}) + + +/// SSX is executing an interrupt handler of any priority. + +#define __ssx_kernel_context_any_interrupt() \ + ({ \ + __SsxKernelContext __ctx; \ + __ctx.value = mfspr(SPRN_USPRG0); \ + __ctx.merged_fields.interrupt_context;}) + + +/// SSX is executing a critical interrupt handler. + +#define __ssx_kernel_context_critical_interrupt() \ + ({ \ + __SsxKernelContext __ctx; \ + __ctx.value = mfspr(SPRN_USPRG0); \ + __ctx.fields.critical_interrupts;}) + + +/// SSX is executing a non-critical interrupt handler. + +#define __ssx_kernel_context_noncritical_interrupt() \ + ({ \ + __SsxKernelContext __ctx; \ + __ctx.value = mfspr(SPRN_USPRG0); \ + __ctx.fields.noncritical_interrupts && \ + !__ctx.fields.critical_interrupts;}) + + +/// Return the noncritical interrupt nesting level + +#define __ssx_noncritical_level() \ + ({ \ + __SsxKernelContext __ctx; \ + __ctx.value = mfspr(SPRN_USPRG0); \ + __ctx.fields.noncritical_interrupts; }) + + +/// Return the critical interrupt nesting level + +#define __ssx_critical_level() \ + ({ \ + __SsxKernelContext __ctx; \ + __ctx.value = mfspr(SPRN_USPRG0); \ + __ctx.fields.critical_interrupts; }) + + +// SSX requires the port to define the type SsxThreadQueue, which is a +// priority queue (where 0 is the highest priority). This queue must be able +// to handle SSX_THREADS + 1 priorities (the last for the idle thread) The +// port must also define methods for clearing, insertion, deletion and min +// (with assumed legal priorities). The min operation returns SSX_THREADS if +// the queue is empty (or a queue could be initialized with that entry always +// present - SSX code never tries to delete the idle thread from a thread +// queue). +// +// These queues are used both for the run queue and the pending queue +// associated with every semaphore. +// +// On PPC405 with 32 threads (implied), this is a job for a uint32_t and +// cntlzw(). + +static inline void +__ssx_thread_queue_clear(volatile SsxThreadQueue *queue) +{ + *queue = 0; +} + +static inline void +__ssx_thread_queue_insert(volatile SsxThreadQueue *queue, SsxThreadPriority priority) +{ + *queue |= (0x80000000u >> priority); +} + +static inline void +__ssx_thread_queue_delete(volatile SsxThreadQueue *queue, SsxThreadPriority priority) +{ + *queue &= ~(0x80000000u >> priority); +} + +static inline SsxThreadPriority +__ssx_thread_queue_min(volatile SsxThreadQueue *queue) +{ + return cntlzw(*queue); +} + +static inline int +__ssx_thread_queue_member(volatile SsxThreadQueue *queue, SsxThreadPriority priority) +{ + return ((*queue >> (31 - priority)) & 1); +} + +static inline void +__ssx_thread_queue_union(volatile SsxThreadQueue *queue0, + volatile SsxThreadQueue *queue1) +{ + *queue0 |= *queue1; +} + +static inline int +__ssx_thread_queue_count(volatile SsxThreadQueue* queue) +{ + return __builtin_popcount(*queue); +} + + +/// This macro is used to call __ssx_start_threads() using the kernel stack, +/// in a SSX_NONCRITICAL critical section. + +#define __ssx_call_ssx_start_threads() \ + do { \ + SsxMachineContext ctx; \ + ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); \ + asm volatile ("mr 1, %0; mtlr %1; blrl" : : \ + "r" (__ssx_noncritical_stack), \ + "r" (__ssx_start_threads)); \ + SSX_PANIC(SSX_START_THREADS_RETURNED); \ + } while (0) + + +#endif /* __ASSEMBLER__ */ + +/// The __SsxKernelContext 'thread_mode' bit as a flag + +#define PPC405_THREAD_MODE 0x80 + + +#ifndef __ASSEMBLER__ + +/// Code breakpoints for PPC405 +/// +/// This macro inserts a special PPC405-only breakpoint into the object code +/// at the place the macro invocation appears. This facility is designed for +/// VBU/VPO procedure debugging. This type of breakpoint may not be required +/// on real hardware as we will then have the full power of RISCWatch, gdb, +/// etc. Once inserted into the code, code breakpoints can be enabled or +/// disabled by manipulating the global variable _code_breakpoint_enable, +/// which defaults to 1. +/// +/// The code breakpoint is implemented as a setup routine and a teardown +/// routine, executed in an SSX_CRITICAL critical section. The actual break +/// will occur at the address of the call of the teardown routine, in the +/// context of the calling code. The setup routine saves the state of DBCR0/1 +/// and IAC4, then programs the DBCR for an external debug mode, IAC4 +/// breakpoint. The IAC4 breakpoint is set for the address of the call of the +/// teardown routine. The teardown routine simply restores the state of the +/// debug registers that existed before the code breakpoint. +/// +/// Once hit, restarting from the break requires clearing IAC4 and restarting +/// instructions: +/// +/// \code +/// +/// putspr pu.occ iac4 0 +/// cipinstruct pu.occ start +/// +/// \endcode +/// +/// The above restart processes is also encapsulated as the p8_tclEcmd +/// procedure 'unbreakOcc'. +/// +/// In code built for the Simics environment (i.e., with the preprocessor +/// macro SIMICS_ENVIRONMENT=1) this macro simply expands into +/// SIMICS_MAGIC_BREAKPOINT, and simulation can be continued from the break as +/// normal. This Simics magic breakpoint is also under the control of +/// _code_breakpoint_enable. In code not built with SIMICS_ENVIROMENT=1, note +/// that the CODE_BREAKPOINT is ignored by the Simics PPC405 model as it does +/// not model debug events. + +#if defined(SIMICS_ENVIRONMENT) && (SIMICS_ENVIRONMENT != 0) +#define CODE_BREAKPOINT \ + do { \ + if (_code_breakpoint_enable) { \ + SIMICS_MAGIC_BREAKPOINT; \ + } \ + } while (0) +#else +#define CODE_BREAKPOINT \ + do { \ + if (_code_breakpoint_enable) { \ + SsxMachineContext __ctx; \ + ssx_critical_section_enter(SSX_CRITICAL, &__ctx); \ + _code_breakpoint_prologue(); \ + _code_breakpoint_epilogue(); \ + ssx_critical_section_exit(&__ctx); \ + } \ + } while (0) +#endif + +void +_code_breakpoint_prologue(void); + +void +_code_breakpoint_epilogue(void); + +extern uint32_t _code_breakpoint_enable; + +#endif // __ASSEMBLER__ + + +#endif /* __PPC405_H__ */ diff --git a/src/ssx/ppc405/ppc405_boot.S b/src/ssx/ppc405/ppc405_boot.S new file mode 100755 index 0000000..1f4a4f9 --- /dev/null +++ b/src/ssx/ppc405/ppc405_boot.S @@ -0,0 +1,242 @@ +// $Id: ppc405_boot.S,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_boot.S,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_boot.S +/// \brief SSX bootloader for PPC405 + + .nolist +#include "ssx.h" + .list + +### SSX Bootloader for PPC405 +### +### This is the basic restart initialization of the processor. +### Parts of this code were derived from examples in the IBM OSopen +### OpenBIOS for the 405GP written by James Burke. +### +### This code does not really do very much, just makes sure that there will +### be a reasonable state in the machine when control is turned over to +### the SSX application. Any core setup that requires SPR access will be done +### here. All other setup is expected to take place in system-specific +### routines. +### +### From the PowerPC 405-S Embedded Core User's manual: +### +### "In general, the contents of SPRs are undefined after a core, chip or +### system reset. Some SPRs retain the content they had before the reset +### occurred." +### +### Registers fully reset: +### DBCR1 - Data compares disabled +### DCCR - Data cache disabled +### DCWR - Data cache write-through disabled +### ESR - No exception syndromes +### ICCR - Instruction cache disabled +### MSR - No exceptions/interrupts are allowed +### SLER - Storage is big-endian +### SU0R - Storage is uncompressed +### +### Registers partially reset: +### CCR0 = 0x00700000 - Sets ICU and DCU PLB Priority +### DBCR0 [EDM] = 0 - External debug mode disabled +### [RST] = 0 - No reset action +### DBSR [MRR] = x - x indicates most recent reset action +### SGR = 0xffffffff - Storage is guarded +### TCR [WRC] = 0 - Watchdog timer reset disabled +### TSR [WRS] = x - x is a copy of TCR[WRC] Watchdog reset status +### [PIS] = x - undefined + + .global_function __ssx_boot + .global __reset_trap + +__ssx_boot: + + ## Trap the reset for the debugger. Set R0 to a non-zero value in the + ## debugger to continue. + + .if PPC405_RESET_TRAP + li %r0, 0 +__reset_trap: + cmpwi %r0, 0 + beq __reset_trap + .endif + + ## First the real-mode memory parameters are set up as configured + ## for the system and/or application. There are no defaults for these 6 + ## configuration options - they must always be supplied. + + _liwa %r3, PPC405_ICCR_INITIAL + mticcr %r3 + _liwa %r3, PPC405_DCCR_INITIAL + mtdccr %r3 + _liwa %r3, PPC405_DCWR_INITIAL + mtdcwr %r3 + _liwa %r3, PPC405_SGR_INITIAL + mtsgr %r3 + _liwa %r3, PPC405_SU0R_INITIAL + mtsu0r %r3 + _liwa %r3, PPC405_SLER_INITIAL + mtsler %r3 + + ## Next the I and D caches are invalidated. + ## NB: The only reason we can do a BL at this point is because we + ## know that these routines do not try to save the LR on the stack. + + bl icache_invalidate_all + bl dcache_invalidate_all + + ## Set up PowerPC EABI constant registers. These registers are never + ## again touched by the SSX kernel or the application (if they are + ## behaving). + + _liw %r2, _SDA2_BASE_ + _liw %r13, _SDA_BASE_ + + ## Clear the timer control register. This masks all timer interrupts. + + mttcr %r3 + + ## Several options are available for dynamic memory ... + ## If none of these options are defined, then it is assumed that + ## the memory area is already set up. + +#if defined(SSX_RUN_FROM_DCACHE) + + ## SSX can run from the DCACHE. In order for this to work, the + ## the linker script must set the symbol __ssx_ram_vma to the + ## beginning of a 128MB memory region marked as cacheable in the + ## application-defined PPC405_DCCR_INITIAL. + ## + ## Note that there is typically no backing store for this data. Before + ## going further, all data cache blocks must be allocated with 'dcbz'. + ## Should a subsequent programming error cause the eviction of + ## a dirty line, a machine check exception will result. + + _liw %r3, __ssx_ram_vma + _liwa %r4, DCACHE_LINES + mtctr %r4 + +dcbz_loop: + dcbz %r0, %r3 + addi %r3, %r3, CACHE_LINE_SIZE + bdnz dcbz_loop + +#elif defined(SSX_RUN_FROM_MEMORY) + + ## Nothing to do here... + +#else + +#error "One of SSX_RUN_FROM_DCACHE or SSX_RUN_FROM_MEMORY must be defined" + +#endif /* SSX_RUN_FROM_xxx */ + + ## The stack pointer is initialized for use by the remainder of the + ## initialization, including the application main(). The linker script + ## defines the initial stack area. + ## + ## Stacks are always 8-byte aligned. A '0' is stored at the + ## stack pointer to indicate the end of the stack chain. Stack frames + ## always consist of at least 8 bytes - the backchain pointer and the + ## slot above the backchain pointer for the callee's LR. + + _liw %r1, _SSX_INITIAL_STACK + _clrfield %r1, %r1, 3, 29 # 8-byte align + li %r3, 0 + stwu %r3, -8(%r1) + + ## USPRG0 (__SsxKernelContext) is initialized to 0 + ## indicating that the SSX kernel is not in thread mode, and no + ## interrupts are active. + + li %r3, 0 + mtusprg0 %r3 + + ## Set up the initial value of Debug Control Register 0. Note that + ## DBCR1 is specified to be cleared at reset. VBU simulation requested + ## an option that this register not be modified so that they could + ## completely control debug behavior from reset of the 405. + +#ifndef NO_INIT_DBCR0 + _liwa %r3, PPC405_DBCR0_INITIAL + mtdbcr0 %r3 +#endif + + ## The exception vector prefix is set - it must be 64KB aligned. + + _liw %r3, __vectors + andi. %r4, %r3, 0xffff + beq 1f + _ssx_panic PPC405_BOOT_VECTORS_NOT_ALIGNED +1: + mtevpr %r3 + isync + + ## The MSR to be used during the rest of intialization is + ## established. This MSR should NOT enable critical or non-critical + ## interrupts, but could enable machine check exceptions. + + _liwa %r3, PPC405_MSR_INITIAL + mtmsr %r3 + isync + + ## Initialize the CCR0. If it returns non-zero, panic. + + _liwa %r4, PPC405_CCR0_INITIAL # bits_to_set + not %r3, %r4 # bits_to_clear + bl ppc405_ccr0_modify + cmpwi %r3, 0 + beq 1f + _ssx_panic PPC405_BOOT_CCR0_MODIFY_FAILED +1: + +#ifdef SSX_BOOT_FROM_ROM + + ## NB: I don't think the old linker scripts were necessarily the most + ## optimal. We need to revisit this if we actually do ROM boots in SSX + ## Version 2. Not sure the comments are correct. + + ## Data is copied from the initial ROM image to the RAM. The + ## address symbols are defined in the linker command file. The linker + ## will have zeroed this area in the ROM image. + + liw %r3, __ssx_ram_lma - 4 # src + liw %r4, __ssx_ram_vma - 4 # dest + liw %r5, __ssx_ram_size + liw %r6, 2 + srw %r5, %r5, %r6 # Number of word transfers + mtctr %r5 + +copy_loop: + lwzu %r5, 4(%r3) + stwu %r5, 4(%r4) + bdnz copy_loop + +#endif /* SSX_BOOT_FROM_ROM */ + + + ## Call the system setup code. + + bl __ppc405_system_setup + + ## Call the application. If for some reason we return from + ## the call of the application we call an alternate entry point of the + ## idle thread. + ## + ## An initial argc/argv can be passed into main(). argc is expected to + ## be a 32-bit immediate integer, and argv is expected to be a 32-bit + ## absolute or relocatable expression. + + _liwa %r3, PPC405_ARGC_INITIAL + _liw %r4, PPC405_ARGV_INITIAL + bl __ssx_main + + b __ssx_idle_thread_from_bootloader + + .epilogue __ssx_boot + diff --git a/src/ssx/ppc405/ppc405_breakpoint.S b/src/ssx/ppc405/ppc405_breakpoint.S new file mode 100644 index 0000000..3adbd13 --- /dev/null +++ b/src/ssx/ppc405/ppc405_breakpoint.S @@ -0,0 +1,103 @@ +// $Id: ppc405_breakpoint.S,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_breakpoint.S,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file breakpoint.S +/// \brief Implementation of code breakpoints for VBU/VPO +/// +/// The operation of these short assembler routines is introduced as part of +/// the documentation for the CODE_BREAKPOINT macro. + + .nolist +#include "ssx.h" + .list + +#ifdef DOXYGEN_ONLY +void _code_breakpoint_prologue(void); +#endif + +/// \cond + + _sprinstrs iac4, SPRN_IAC4 + + .global_function _code_breakpoint_prologue +_code_breakpoint_prologue: + + // Save the DBCR0/1 and IAC4 + + mfdbcr0 %r3 + mfdbcr1 %r4 + mfiac4 %r5 + _stwsd %r3, _saved_dbcr0 + _stwsd %r4, _saved_dbcr1 + _stwsd %r5, _saved_iac4 + + // Set IAC4 to the contents of LR, which will cause a break in the + // caller's context. + + mflr %r3 + mtiac4 %r3 + + // Reprogram to external debug mode, trigger on IAC4 compare, freeze + // timers. Clear data compare setup for good measure. + + _liwa %r3, DBCR0_EDM | DBCR0_IA4 | DBCR0_FT + mtdbcr0 %r3 + _liwa %r3, 0 + mtdbcr1 %r3 + + isync + blr + + .epilogue _code_breakpoint_prologue + + .section .sdata + .balign 4 + + .global _code_breakpoint_enable +_code_breakpoint_enable: + .long 1 + +_saved_dbcr0: + .long 0 +_saved_dbcr1: + .long 0 +_saved_iac4: + .long 0 + +/// \endcond + + +#ifdef DOXYGEN_ONLY +void _code_breakpoint_epilogue(void); +#endif + +/// \cond + + .global_function _code_breakpoint_epilogue +_code_breakpoint_epilogue: + + // Restore the DBCR0/1 and IAC4 + + _lwzsd %r3, _saved_dbcr0 + _lwzsd %r4, _saved_dbcr1 + _lwzsd %r5, _saved_iac4 + mtdbcr0 %r3 + mtdbcr1 %r4 + mtiac4 %r5 + + // Clear IA4 status + + _liwa %r3, DBSR_IA4 + mtdbsr %r3 + + isync + blr + + .epilogue _code_breakpoint_epilogue + +/// \endcond diff --git a/src/ssx/ppc405/ppc405_cache.h b/src/ssx/ppc405/ppc405_cache.h new file mode 100755 index 0000000..02bd4f5 --- /dev/null +++ b/src/ssx/ppc405/ppc405_cache.h @@ -0,0 +1,113 @@ +#ifndef __PPC405_CACHE_H__ +#define __PPC405_CACHE_H__ + +// $Id: ppc405_cache.h,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_cache.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_cache.h +/// \brief PowerPC 405 cache management header for SSX +/// +/// The data cache flush/invalidate macros defined here create a compiler +/// memory barrier that will cause GCC to flush/invalidate all memory data +/// held in registers before the macro. + +#ifndef __ASSEMBLER__ + +/// Determine cache-alignment of a pointer or byte-count +#define cache_aligned(x) \ + ((((unsigned long)(x)) & (POW2_32(LOG_CACHE_LINE_SIZE) - 1)) == 0) + +/// Cache-align a pointer or byte count. If the 'direction' is <= 0 then we +/// round down, else round up. +#define cache_align(x, direction) \ + ({ \ + unsigned long __x = (unsigned long)(x); \ + unsigned long __r; \ + if ((direction) <= 0) { \ + __r = __x & ~(((unsigned long)CACHE_LINE_SIZE) - 1); \ + } else { \ + if (__x % CACHE_LINE_SIZE) { \ + __r = __x + (CACHE_LINE_SIZE - (__x % CACHE_LINE_SIZE)); \ + } \ + } \ + (void *)__r; \ + }) + +/// Data Cache Block Flush +#define dcbf(p) asm volatile ("dcbf 0, %0" : : "r" (p) : "memory") + +/// Data Cache Block Touch +#define dcbt(p) asm volatile ("dcbt 0, %0" : : "r" (p) : "memory") + +/// Data Cache Block Invalidate (Privileged) +#define dcbi(p) asm volatile ("dcbi 0, %0" : : "r" (p) : "memory") + +/// Instruction Cache Block Invalidate +#define icbi(p) asm volatile ("icbi 0, %0" : : "r" (p) : "memory") + +/// Instruction Cache Block Touch +#define icbt(p) asm volatile ("icbt 0, %0" : : "r" (p) : "memory") + +void +icache_invalidate_all(void); + +void +dcache_invalidate_all(void); + +void +dcache_flush_all(void); + +void +dcache_invalidate(void *p, size_t bytes); + +void +dcache_flush(void *p, size_t bytes); + +/// Invalidate a line in the D-cache +/// +/// \param p An address withing the cache line to be invalidated. +/// +/// The dcache_invalidate_line() API is used to invalidate a single cache line +/// containing the address \a p. Note that invalidation is a destructive +/// operation that may cause the loss of information. It is the caller's +/// responsibility to insure that no useful data is inadverdently invalidated. +/// D-cache invalidation is more-or-less a no-op for data either not in the +/// cache or marked as non-cacheable. +/// +/// This API always issues a sync() after the invalidation. + +static inline void +dcache_invalidate_line(void *p) +{ + dcbi(p); + sync(); +} + +/// Flush and invalidate a line from the D-cache +/// +/// \param p An address within the cache line to be flushed. +/// +/// The dcache_flush_line() API can be used as a shortcut to flush and +/// invalidate a single cache line. Note that flushing is not a destructive +/// operation in the sense that no information is lost, however the caller +/// must make sure that the entirity of the data to be flushed is contained in +/// the line that includes the address \a p. D-cache flush is more-or-less a +/// no-op for data either not in the cache or marked as non-cacheable. +/// +/// This API always issues a sync() after the flush. + +static inline void +dcache_flush_line(void *p) +{ + dcbf(p); + sync(); +} + +#endif /* __ASSEMBLER__ */ + +#endif /* __PPC405_CAHE_H__ */ diff --git a/src/ssx/ppc405/ppc405_cache_core.c b/src/ssx/ppc405/ppc405_cache_core.c new file mode 100755 index 0000000..a03f5e2 --- /dev/null +++ b/src/ssx/ppc405/ppc405_cache_core.c @@ -0,0 +1,115 @@ +// $Id: ppc405_cache_core.c,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_cache_core.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_cache_core.c +/// \brief Core cache management routines required of any PPC405 configuration +/// of SSX that interacts with DMA devices using cacheable memory. +/// +/// The entry points in this file are considered 'core' routines that will +/// always be present at runtime in any SSX application. +/// +/// \todo The compiler generates wierd assembly language for these cache +/// management APIs - probably due to the "volatile" asm - it may be best to +/// recode them directly in assembler. + +#include "ssx.h" + +/// Invalidate a range of addresses from the D-cache +/// +/// \param p A pointer to the memory area to be invalidated. +/// +/// \param bytes The size (in bytes) of the area to invalidate. +/// +/// The dcache_invalidate() API is used to invalidate an arbitrary range of +/// memory in the cache. Note that invalidation is a destructive operation +/// that may cause the loss of information. This API will invalidate all +/// cache lines from the line containing the address \a p, to the line +/// containing the address \a p + \a size - 1. (If \a size == 0 this call is +/// a NOP.) It is the caller's responsibility to insure that no useful data is +/// inadverdently invalidated. D-cache invalidation is more-or-less a no-op +/// for data either not in the cache or marked as non-cacheable. +/// +/// This API always issues a sync() after the invalidation, even in the event +/// of \a size == 0. +/// +/// \note For invalidating small blocks of data where some alignmment +/// constraints are known it may be more efficient to use +/// dcache_invalidate_line() rather than this API. + +void +dcache_invalidate(void *p, size_t bytes) +{ + size_t lines; + + if (bytes != 0) { + lines = 1; + bytes -= + MIN((CACHE_LINE_SIZE - ((unsigned long)p % CACHE_LINE_SIZE)), + bytes); + lines += bytes / CACHE_LINE_SIZE; + if (!cache_aligned(bytes)) { + lines++; + } + while (lines--) { + dcbi(p); + p += CACHE_LINE_SIZE; + } + } + sync(); +} + + +/// Flush and invalidate a range of addresses from the D-cache +/// +/// \param p A pointer to a memory area to be invalidated. +/// +/// \param bytes The size (in bytes) of the area to invalidate. +/// +/// The dcache_flush() API is used to flush and invalidate an arbitrary range +/// of memory from the D-cache. Note that flushing is not a destructive +/// operation in the sense that no information is lost. This API will flush +/// and invalidate all cache lines from the line containing the address \a p, +/// to the line containing the address \a p + \a size - 1. (If \a size == 0 +/// this call is a NOP.) D-cache flush is more-or-less a no-op for data +/// either not in the cache or marked as non-cacheable. +/// +/// This API always issues a sync() after the flush, even in the event of \a +/// size == 0. +/// +/// \note For flushing small blocks of data where some alignmment constraints +/// are known it may be more efficient to use dcache_flush_line() rather than +/// this API. + + +void +dcache_flush(void *p, size_t bytes) +{ + size_t lines; + + if (bytes != 0) { + lines = 1; + bytes -= + MIN((CACHE_LINE_SIZE - ((unsigned long)p % CACHE_LINE_SIZE)), + bytes); + lines += bytes / CACHE_LINE_SIZE; + if (!cache_aligned(bytes)) { + lines++; + } + while (lines--) { + dcbf(p); + p += CACHE_LINE_SIZE; + } + } + sync(); +} + + + + + + diff --git a/src/ssx/ppc405/ppc405_cache_init.S b/src/ssx/ppc405/ppc405_cache_init.S new file mode 100755 index 0000000..c4bed0e --- /dev/null +++ b/src/ssx/ppc405/ppc405_cache_init.S @@ -0,0 +1,314 @@ +// $Id: ppc405_cache_init.S,v 1.3 2014/06/26 12:59:35 cmolsen Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_cache_init.S,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_cache_init.S +/// \brief PPC405-specific procedures required for cache initialization +/// +/// The routines in this file are not part of SSX per se, but are included +/// with SSX because they are used during initialialization and boot. +/// +/// These are 'initialization' routines used by the SSX bootloader and other +/// application initialization code and may not be needed after +/// boot/initialization of the SSX application. +/// +/// See the documents './doc/PowerPC 405-S Core Errata' and './doc/PowerPC +/// 405-S Core Errata Impact on PGP OCC Firmware' for information on the +/// CPU_xxx errata. + + .nolist +#include "ssx.h" +#include "ppc405_context.h" + .list + +/// \fn void icache_invalidate_all() +/// \brief Invalidate the entire I-Cache +/// +/// In the PPC405 a single instruction invalidates the entire I-Cache, +/// therefore this routine need not be executed from a critical section. +/// +/// +/// This API always issues an isync() after the invalidation. +#ifdef DOXYGEN_ONLY +void icache_invalidate_all(); +#endif +/// \cond + + .global_function icache_invalidate_all + +icache_invalidate_all: + + _ssx_critical_section_enter SSX_SUPERCRITICAL, %r5, %r6 + + # Workaround for CPU_121: The iccci instruction may errantly + # cause a Data TLB exception. Workaround avoids this erratum by + # temporarily disabling data address translation. + + mfmsr %r3 + andi. %r4, %r3, 0xffef + mtmsr %r4 + isync + + ## On the 405, iccci invalidates the entire I-Cache. + + iccci %r0,%r0 + + # Restore MSR/DR bit + mtmsr %r3 + isync + + _ssx_critical_section_exit %r5 + + blr + + .epilogue icache_invalidate_all + +/// \endcond + + +/// \fn void dcache_invalidate_all() +/// \brief Invalidate the entire D-Cache +/// +/// This API operates in an SSX_SUPERCRITICAL critical section. This API always +/// issues a sync() after the invalidation. +#ifdef DOXYGEN_ONLY +void dcache_invalidate_all(); +#endif +/// \cond + + .global_function dcache_invalidate_all + +dcache_invalidate_all: + + _ssx_critical_section_enter SSX_SUPERCRITICAL, %r5, %r6 + + ## We loop through addresses 0 ... (DCACHE_SIZE / DCACHE_WAYS) - 1 + ## invalidating the D-Cache. The dccci instruction on the 405 + ## invalidates both ways. + + li %r3, 0 + _liwa %r4, (DCACHE_LINES / DCACHE_WAYS) + mtctr %r4 + +1: + dccci %r0, %r3 + addi %r3, %r3, CACHE_LINE_SIZE + bdnz 1b + + sync + + _ssx_critical_section_exit %r5 + + blr + + .epilogue dcache_invalidate_all + +/// \endcond + + +#ifndef USE_GENERIC_DCACHE_FLUSH_ALL +#define USE_GENERIC_DCACHE_FLUSH_ALL 1 +#endif + +/// \fn void dcache_flush_all() +/// \brief Flush the entire D-Cache (Generic) +/// +/// This API is necessary whenever it is required to change data cacheability +/// after boot. The D-cache is scanned, and any lines present in the cache are +/// flushed. This API operates in an SSX_SUPERCRITICAL critical section. This +/// API always issues a sync() after the flush. +/// +/// This is a generic implementation that should work on all PPC405 +/// systems. If something is known about the memory configuration then SSX +/// ports can implement better/more efficient flush-all algorithms. +/// +/// This API runs with data translation disabled. This is necessary for +/// correctness, and also obviates the need to check whether a cache entry is +/// valid before flushing the entry. +/// +/// This API is currently a NOP in Simics simulations which complain that the +/// dcread instruction is implemented as a NOP. +#ifdef DOXYGEN_ONLY +void dcache_flush_all(); +#endif +/// \cond + +#if USE_GENERIC_DCACHE_FLUSH_ALL + + .global_function dcache_flush_all +dcache_flush_all: + +#if !SIMICS_ENVIRONMENT + + ## %r3 used as temp throughout + ## %r4 holds the original MSR throughout + ## %r8 used as a temp throughout + ## %r9 used as a temp throughout + + _ssx_critical_section_enter SSX_SUPERCRITICAL, %r4, %r3 + + mfmsr %r3 + _clrbit %r3, %r3, MSR_DR_BIT + mtmsr %r3 + isync + + ## %r5 counts the congruence class address + ## CTR counts the number of congruence classes + + li %r5, 0 + _liwa %r9, (DCACHE_LINES / DCACHE_WAYS) + mtctr %r9 + + ## %r6 has the CCR0 value for reading DCACHE tag on way A + ## %r7 has the CCR0 value for reading DCACHE tag on way B + ## %r8 has the cache tag mask + + mfccr0 %r6 + _liwa %r9, 0x00000011 + andc %r6, %r6, %r9 # Clear DCREAD control bits + ori %r6, %r6, 0x0010 + ori %r7, %r6, 0x0001 + _liwa %r8, DCACHE_TAG_MASK # Cache tag mask + +dflush_loop: + + ## Way A + + mtccr0 %r6 # Set CCR0 for DCREAD + dcread %r9, %r0, %r5 + and %r9, %r9, %r8 # Mask out cache tag + or %r9, %r9, %r5 # OR in the congruence class address + dcbf %r0, %r9 # Flush the line + + ## Way B + + mtccr0 %r7 # Set CCR0 for DCREAD + dcread %r9, %r0, %r5 + and %r9, %r9, %r8 # Mask out cache tag + or %r9, %r9, %r5 # OR in the congruence class address + dcbf %r0, %r9 # Flush the line + + addi %r5, %r5, CACHE_LINE_SIZE + bdnz dflush_loop + + ## Restore the MSR and return + + _ssx_critical_section_exit %r4 + +#endif // SIMICS_ENVIRONMENT + + blr + + .epilogue dcache_flush_all + +#endif // USE_GENERIC_DCACHE_FLUSH_ALL + +/// \endcond + +/// \fn int ppc405_ccr0_modify(uint32_t bits_to_clear, uint32_t bits_to_set) +/// \brief A special code sequence to modify the Cache Control Register 0 (CCR0) +/// +/// \param bits_to_clear A positive mask of bits in CCR0 that will be cleared +/// by this call. +/// +/// \param bits_to_set A positive mask of bits in CCR0 that will be set by +/// this call. +/// +/// The code that implements this procedure \e must be in I-cacheable memory. +/// +/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion. +/// +/// \retval -SSX_ILLEGAL_CONTEXT_PPC405_CACHE The code implementing the API +/// is not cacheable. +/// +#ifdef DOXYGEN_ONLY +int ppc405_ccr0_modify(uint32_t bits_to_clear, uint32_t bits_to_set); +#endif +/// \cond + + ## The implementation is based on an example from the 405GP manual. + + .global_function ppc405_ccr0_modify + +ppc405_ccr0_modify: + + ## %r3 is parameter bits_to_clear + ## %r4 is parameter bits_to_set + ## %r5 will hold the original MSR + ## %r6 will hold the address of the update code. + ## %r7, %r8, %r9 are used for computation. + + ## Disable external and critical interrupts + + mfmsr %r5 + _liwa %r6, (MSR_CE | MSR_EE) + andc %r6, %r5, %r6 + mtmsr %r6 # Interrupts disabled + sync + + .if SSX_ERROR_CHECK_API + + ## Check for cacheability of the code sequence + + _liw %r6, ccr0_modify_doit + extrwi %r7, %r6, 5, 0 # Upper 5 bits are address range + mficcr %r8 + _liwa %r9, 0x80000000 + srw %r9, %r9, %r7 # %r9 holds bit to check in %r8 + and. %r9, %r9, %r8 + bne ccr0_modify_continue + + ## Whoops! Code not cacheable; restore MSR and return error code. + + .if SSX_ERROR_PANIC + + _ssx_panic SSX_ILLEGAL_CONTEXT_PPC405_CACHE + + .else + + _liwa %r3, -SSX_ILLEGAL_CONTEXT_PPC405_CACHE + mtmsr %r5 + isync + + .endif + + blr + + .endif + + ## Touch the code sequence into the I-Cache and do it. + +ccr0_modify_continue: + icbt %r0, %r6 + isync # Erratum CPU_208 + b ccr0_modify_doit + + ## The ICBT is repeated to insure that the code is really in + ## the cache. The bits are cleared, set, updated and we exit. + + .cache_align # Must be cache-line aligned +ccr0_modify_doit: + icbt %r0, %r6 + isync + mfccr0 %r7 + andc %r7, %r7, %r3 # Clear some bits + or %r7, %r7, %r4 # Set some bits + mtccr0 %r7 + isync + + ## Restore MSR and return 0. + + li %r3, 0 + mtmsr %r5 + isync + blr + + .epilogue ppc405_ccr0_modify + +/// \endcond diff --git a/src/ssx/ppc405/ppc405_context.h b/src/ssx/ppc405/ppc405_context.h new file mode 100755 index 0000000..3019358 --- /dev/null +++ b/src/ssx/ppc405/ppc405_context.h @@ -0,0 +1,594 @@ +#ifndef __PPC405_CONTEXT_H__ +#define __PPC405_CONTEXT_H__ + +// $Id: ppc405_context.h,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_context.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_context.h +/// \brief PPC405 Machine and Thread context for SSX + +/// \page ppc405_machine_context PPC405 Assembler Macros for SSX Machine +/// Context (Critical Sections) +/// +/// \section _ssx_enter_critical \b _ssx_critical_section_enter/exit +/// +/// These macro encapsulates the instruction sequences required to enter and +/// exit critical sections, along with the machine context save for later +/// exiting the critical section. +/// +/// \arg \c priority Either \c SSX_CRITICAL, \c SSX_NON_CRITICAL or +/// SSX_SUPERCRITICAL (for \c ssx_critical_section_enter). +/// +/// \arg \c ctxreg A register that will hold (holds) the machine context (MSR) +/// prior to entering the critical section (to be restored) for \c +/// _ssx_critical_section_enter (\c _ssx_critical_section_exit). +/// +/// \arg \c scrreg A scratch register required for the computation of +/// \c _ssx_critical_section_enter. +/// +/// Forms: +/// +/// \b _ssx_critical_section_enter \a priority, \a ctxreg, \a scrreg - Enter a +/// critical section \n +/// \b _ssx_critical_section_exit \a ctxreg - Exit a critical section + +#ifdef __ASSEMBLER__ + + .set _msr_ee_bit, MSR_EE_BIT + .set _msr_ce_bit, MSR_CE_BIT + + .macro _ssx_critical_section_enter priority, ctxreg, scrreg + mfmsr \ctxreg + .if ((\priority) == SSX_CRITICAL) + _clrbit \scrreg, \ctxreg, _msr_ee_bit + _clrbit \scrreg, \scrreg, _msr_ce_bit + mtmsr \scrreg + .elseif ((\priority) == SSX_SUPERCRITICAL) + _liwa \scrreg, (MSR_APE | MSR_WE | MSR_CE | MSR_EE | MSR_ME | MSR_DWE | MSR_DE) + andc \scrreg, \ctxreg, \scrreg + mtmsr \scrreg + .elseif ((\priority) == SSX_NONCRITICAL) + wrteei 0 + .else + .error "'priority' was not one of SSX_CRITICAL, SSX_NONCRITICAL or SSX_SUPERCRITICAL" + .endif + isync + .endm + + .macro _ssx_critical_section_exit ctxreg + mtmsr \ctxreg + isync + .endm + +// **************************************************************************** +// SSX context save/restore macros for 32-bit Embedded PowerPC +// **************************************************************************** + +// All stack frames are 8-byte aligned in conformance with the EABI. SSX +// never saves or restores GPR2 or GPR13. GPR13 is constant in (E)ABI +// applications - the base of the read-write small data area. GPR2 is +// system-reserved in ABI applications, and is the base for read-only small data +// in EABI applications. + +// A fair amount of complexity is involved in handling the non-critical and +// critical interrupt levels, and the emphasis on performance of fast-mode +// interrupt handlers. Several different approaches and philosophies could +// have been implemented - this is only one. In this implementation +// critical/non-critical interrupt levels are treated more or less the same, +// and the interrupt priority is just that - a kind of preemption priority. +// Critical interrupt handling does have a little less overhead because it +// does not have a thread scheduling step at the end. + +// A full context save takes place in 3 or 4 steps. Thread switches always do +// steps 1, 2 and 3. +// 1. The fast context that is always saved in response to every interrupt; +// 1a. The optional save/update of the kernel context for interrupts. +// 2. The (volatile - fast) context that is saved if an interrupt handler +// switches from fast-mode to full-mode. +// 3. The non-volatile context that is saved when a thread is switched out. + +// USPRG0 holds the __SsxKernelContext structure (defined in ppc405.h) that +// represents the current kernel context. The layout is as follows: +// +// Bits Meaning +// ============== +// 0:7 The critical interrupt count +// 8:15 The non-critical interrupt count +// 16:23 The IRQ currently being processed +// 24 The 'thread_mode' flag +// 25:31 The thread priority of the running thread +// +// When SSX is initialized USPRG0 is initialized to 0. When thread-mode is +// entered (by ssx_start_threads()) bit 24 is set to 1. In order to support +// PgP/OCC firmware, once initialized (with ssx_initialize()) SSX can simply +// handle interrupts, reverting back to the non-thread-mode idle loop when +// there's nothing to do. +// +// Note that it would require a serious error for the interrupt counts to ever +// equal or exceed 2**8 as this would imply runaway reentrancy and stack +// overflow. In fact it is most likely an error if an interrupt handler is +// ever re-entered while active. + +// Registers SRR2 and SRR3 are always saved in IRQ context because +// __ssx_irq_fast2full must save the (volatile - fast) context to provide +// working registers before it can look at USPRG0 to determine critical +// vs. non-critical context. However, when restoring a non-critical interrupt +// or thread these registers need not be restored. SRR2 and SRR3 are never +// saved or restored for thread context switches, because threads always +// operate at noncritical level. + +// When MMU protection is enabled, relocation/protection is re-established +// immediately upon entry to the interrupt handler, before any memory +// operations (load/store) take place. This requires using SPRG0 and SPGR4 +// for temporary storage for noncritical/critical handlers respectively in +// accordance with the SSX conventions for SPRGn usage by fast-mode +// interrupts. + + ## ------------------------------------------------------------ + ## Unused registers for embedded PowerPC + ## ------------------------------------------------------------ + + ## Registers GPR2 and GPR13 are never saved or restored. In ABI and + ## EABI applications these registers are constant. + + .set UNUSED_GPR2, 0x2 # Dedicated; EABI read-only small data area + .set UNUSED_GPR13, 0xd # Dedicated; (E)ABI read-write small data area + + ## ------------------------------------------------------------ + ## Flags for context push/pop + ## ------------------------------------------------------------ + + .set SSX_THREAD_CONTEXT, 0 + .set SSX_IRQ_CONTEXT, 1 + + ## ------------------------------------------------------------ + ## The SSX fast context layout for Embedded PowerPC + ## ------------------------------------------------------------ + + .set SSX_FAST_CTX_GPR1, 0x00 # Dedicated; Stack pointer + .set SSX_FAST_CTX_HANDLER_LR, 0x04 # Slot for handler to store LR + .set SSX_FAST_CTX_GPR3, 0x08 # Volatile; Parameter; Return Value + .set SSX_FAST_CTX_GPR4, 0x0c # Volatile; Parameter + .set SSX_FAST_CTX_GPR5, 0x10 # Volatile; Parameter + .set SSX_FAST_CTX_GPR6, 0x14 # Volatile; Parameter + .set SSX_FAST_CTX_GPR7, 0x18 # Volatile; Parameter + .set SSX_FAST_CTX_CR, 0x1c # Condition register + .set SSX_FAST_CTX_LR, 0x20 # Link register SPRN 0x008 + .set SSX_FAST_CTX_KERNEL_CTX, 0x24 # Saved __SsxKernelContext for IRQ + + .set SSX_FAST_CTX_SIZE, 0x28 # Must be 8-byte aligned + + ## ------------------------------------------------------------ + ## The SSX (volatile - fast) context layout for Embedded PowerPC + ## ------------------------------------------------------------ + + .set SSX_VOL_FAST_CTX_GPR1, 0x00 # Dedicated; Stack pointer + .set SSX_VOL_FAST_CTX_HANDLER_LR, 0x04 # Slot for handler to store LR + .set SSX_VOL_FAST_CTX_GPR0, 0x08 # Volatile; Language specific + .set SSX_VOL_FAST_CTX_GPR8, 0x0c # Volatile; Parameter + .set SSX_VOL_FAST_CTX_GPR9, 0x10 # Volatile; Parameter + .set SSX_VOL_FAST_CTX_GPR10, 0x14 # Volatile; Parameter + .set SSX_VOL_FAST_CTX_GPR11, 0x18 # Volatile + .set SSX_VOL_FAST_CTX_GPR12, 0x1c # Volatile + .set SSX_VOL_FAST_CTX_XER, 0x20 # Fixed-point exception register SPRN 0x001 + .set SSX_VOL_FAST_CTX_CTR, 0x24 # Count register SPRN 0x009 + .set SSX_VOL_FAST_CTX_SRR0, 0x28 # Save/restore register 0 SPRN 0x01a + .set SSX_VOL_FAST_CTX_SRR1, 0x2c # Save/restore register 1 SPRN 0x01b + .set SSX_VOL_FAST_CTX_SRR2, 0x30 # Save/restore register 2 SPRN 0x3de + .set SSX_VOL_FAST_CTX_SRR3, 0x34 # Save/restore register 3 SPRN 0x3df + + .set SSX_VOL_FAST_CTX_SIZE, 0x38 # Must be 8-byte aligned + + ## ------------------------------------------------------------ + ## The SSX non-volatile context layout for Embedded PowerPC + ## ------------------------------------------------------------ + + ## The 'preferred form' for stmw is for the LSB of R31 to fall into the + ## end of a 16-byte aligned block. + + .set SSX_NON_VOL_CTX_GPR1, 0x0 # Dedicated; Stack Pointer + .set SSX_NON_VOL_CTX_HANDLER_LR, 0x4 # Slot for handler to store LR + .set SSX_NON_VOL_CTX_GPR14, 0x8 # Non-volatile + .set SSX_NON_VOL_CTX_GPR15, 0xc # Non-volatile + .set SSX_NON_VOL_CTX_GPR16, 0x10 # Non-volatile + .set SSX_NON_VOL_CTX_GPR17, 0x14 # Non-volatile + .set SSX_NON_VOL_CTX_GPR18, 0x18 # Non-volatile + .set SSX_NON_VOL_CTX_GPR19, 0x1c # Non-volatile + .set SSX_NON_VOL_CTX_GPR20, 0x20 # Non-volatile + .set SSX_NON_VOL_CTX_GPR21, 0x24 # Non-volatile + .set SSX_NON_VOL_CTX_GPR22, 0x28 # Non-volatile + .set SSX_NON_VOL_CTX_GPR23, 0x2c # Non-volatile + .set SSX_NON_VOL_CTX_GPR24, 0x30 # Non-volatile + .set SSX_NON_VOL_CTX_GPR25, 0x34 # Non-volatile + .set SSX_NON_VOL_CTX_GPR26, 0x38 # Non-volatile + .set SSX_NON_VOL_CTX_GPR27, 0x3c # Non-volatile + .set SSX_NON_VOL_CTX_GPR28, 0x40 # Non-volatile + .set SSX_NON_VOL_CTX_GPR29, 0x44 # Non-volatile + .set SSX_NON_VOL_CTX_GPR30, 0x48 # Non-volatile + .set SSX_NON_VOL_CTX_GPR31, 0x4c # Non-volatile + + .set SSX_NON_VOL_CTX_SIZE, 0x50 # Must be 8-byte aligned + + ## ------------------------------------------------------------ + ## Save/restore the fast context + ## + ## 11 Instructions, 8 Loads/Stores : If MMU is disabled + ## 17 Instructions, 8 Loads/Stores : If MMU is enabled + ## ------------------------------------------------------------ + ## + ## Without MMU support, an EIEIO is always executed at the entry point + ## to gauarantee that all memory operations (especially MMIO + ## operations) have completed prior to execution of the interrupt + ## handler. + ## + ## If MMU support is enabled, address translation is re-established + ## immediately at the entry of each interrupt, prior to performing any + ## loads or stores. SSX currently only supports using the MMU for + ## protection, not for address translation. Therfore it is 'legal' + ## to change translation modes a with an MTMSR followed by an + ## ISYNC. This is much simpler then the complex instruction sequence + ## that would be required if we had to set up RFI/RFCI sequences to + ## change the execution context at this point. + ## + ## Note that since we are not really doing address translation, it + ## would also be in keeping with the 'fast interrupt' idea to defer + ## reenabling translation (protection) until the fast-to-full sequence + ## was executed for full-mode interrupts, and run fast-mode interrupts + ## unprotected. However here we chose to run all interrupts with MMU + ## protection. + ## + ## Unfortunately the simple MTMSR;ISYNC sequence exposes a serious bug + ## in the 405-S core that causes the stack-pointer store instruction + ## to generate a seemingly random, *real-mode* address in certain cases + ## when this instruction in a noncritical interrupt prologue is + ## interrupted by a critical interrupt. This bug is described in + ## HW239446. The workaround is to follow the ISYNC sith a SYNC - which + ## eliminates the problem for reasons still unknown. On the bright side + ## this SYNC might also serve the same purpose as the EIEIO in the + ## non-MMU case, guaranteeing that all MMIO has completed prior to the + ## interrupt handler. However without the initial EIEIO we still + ## experience failures, so this seemingly redundant instruction also + ## remains in place. This requirement is assumed to be related to the + ## HW239446 issue. + + .macro _ssx_fast_ctx_push, critical + + .if !PPC405_MMU_SUPPORT + + eieio + + .elseif \critical + + eieio # HW239446? + mtsprg4 %r3 + mfmsr %r3 + ori %r3, %r3, PPC405_RELOCATION_MODE + mtmsr %r3 + isync +#ifndef ALLOW_HW239446 + sync # HW239446! +#endif + mfsprg4 %r3 + + .else + + eieio # HW239446? + mtsprg0 %r3 + mfmsr %r3 + ori %r3, %r3, PPC405_RELOCATION_MODE + mtmsr %r3 + isync +#ifndef ALLOW_HW239446 + sync # HW239446! +#endif + mfsprg0 %r3 + + .endif + + stwu %r1, -SSX_FAST_CTX_SIZE(%r1) # May be corrupted w/o HW239446 + + stw %r3, SSX_FAST_CTX_GPR3(%r1) + stw %r4, SSX_FAST_CTX_GPR4(%r1) + stw %r5, SSX_FAST_CTX_GPR5(%r1) + stw %r6, SSX_FAST_CTX_GPR6(%r1) + stw %r7, SSX_FAST_CTX_GPR7(%r1) + + mfcr %r3 + mflr %r4 + + stw %r3, SSX_FAST_CTX_CR(%r1) + stw %r4, SSX_FAST_CTX_LR(%r1) + + .endm + + + .macro _ssx_fast_ctx_pop + + lwz %r3, SSX_FAST_CTX_CR(%r1) + lwz %r4, SSX_FAST_CTX_LR(%r1) + + mtcr %r3 + mtlr %r4 + + lwz %r3, SSX_FAST_CTX_GPR3(%r1) + lwz %r4, SSX_FAST_CTX_GPR4(%r1) + lwz %r5, SSX_FAST_CTX_GPR5(%r1) + lwz %r6, SSX_FAST_CTX_GPR6(%r1) + lwz %r7, SSX_FAST_CTX_GPR7(%r1) + + lwz %r1, 0(%r1) + + .endm + + ## ------------------------------------------------------------ + ## Save/update the kernel context in response to an interrupt. This is + ## not part of the fast context save because for external interupts the + ## IRQ is not determined until later. + ## ------------------------------------------------------------ + + ## The kernel context is saved, then updated with the currently active + ## IRQ in bits 16:23. The correct interrupt count is incremented and + ## the context is returned to USPRG0. + + .macro _save_update_kernel_context critical, irqreg, ctxreg + + .if \critical + SSX_TRACE_CRITICAL_IRQ_ENTRY \irqreg, \ctxreg + .else + SSX_TRACE_NONCRITICAL_IRQ_ENTRY \irqreg, \ctxreg + .endif + + mfusprg0 \ctxreg + stw \ctxreg, SSX_FAST_CTX_KERNEL_CTX(%r1) + rlwimi \ctxreg, \irqreg, 8, 16, 23 + .if \critical + addis \ctxreg, \ctxreg, 0x0100 + .else + addis \ctxreg, \ctxreg, 0x0001 + .endif + mtusprg0 \ctxreg + + .endm + + ## ------------------------------------------------------------ + ## Fast-mode context pop and RF(C)I. This is only used by + ## interrupt handlers - the thread context switch has its own + ## code to handle updating USPRG0 for thread mode. + ## ------------------------------------------------------------ + + .macro _ssx_fast_ctx_pop_exit critical + + .if SSX_KERNEL_TRACE_ENABLE + .if \critical + bl __ssx_trace_critical_irq_exit + .else + bl __ssx_trace_noncritical_irq_exit + .endif + .endif + + lwz %r3, SSX_FAST_CTX_KERNEL_CTX(%r1) + mtusprg0 %r3 + _ssx_fast_ctx_pop + .if \critical + rfci + .else + rfi + .endif + + .endm + + ## ------------------------------------------------------------ + ## Save/restore the (volatile - fast) context + ## + ## Thread - 15 Instructions, 11 Loads/Stores + ## IRQ - 19(15) Instructions, 13(11) Loads/Stores + ## ------------------------------------------------------------ + + .macro _ssx_vol_fast_ctx_push, irq_context, critical=1 + + stwu %r1, -SSX_VOL_FAST_CTX_SIZE(%r1) + + stw %r0, SSX_VOL_FAST_CTX_GPR0(%r1) + stw %r8, SSX_VOL_FAST_CTX_GPR8(%r1) + stw %r9, SSX_VOL_FAST_CTX_GPR9(%r1) + stw %r10, SSX_VOL_FAST_CTX_GPR10(%r1) + stw %r11, SSX_VOL_FAST_CTX_GPR11(%r1) + stw %r12, SSX_VOL_FAST_CTX_GPR12(%r1) + + mfxer %r8 + mfctr %r9 + mfsrr0 %r10 + mfsrr1 %r11 + + stw %r8, SSX_VOL_FAST_CTX_XER(%r1) + stw %r9, SSX_VOL_FAST_CTX_CTR(%r1) + stw %r10, SSX_VOL_FAST_CTX_SRR0(%r1) + stw %r11, SSX_VOL_FAST_CTX_SRR1(%r1) + + .if (\irq_context & \critical) + mfsrr2 %r8 + mfsrr3 %r9 + + stw %r8, SSX_VOL_FAST_CTX_SRR2(%r1) + stw %r9, SSX_VOL_FAST_CTX_SRR3(%r1) + .endif + + .endm + + + .macro _ssx_vol_fast_ctx_pop, irq_context, critical + + .if (\irq_context & \critical) + lwz %r8, SSX_VOL_FAST_CTX_SRR2(%r1) + lwz %r9, SSX_VOL_FAST_CTX_SRR3(%r1) + + mtsrr2 %r8 + mtsrr3 %r9 + .endif + + lwz %r8, SSX_VOL_FAST_CTX_XER(%r1) + lwz %r9, SSX_VOL_FAST_CTX_CTR(%r1) + lwz %r10, SSX_VOL_FAST_CTX_SRR0(%r1) + lwz %r11, SSX_VOL_FAST_CTX_SRR1(%r1) + + mtxer %r8 + mtctr %r9 + mtsrr0 %r10 + mtsrr1 %r11 + + lwz %r0, SSX_VOL_FAST_CTX_GPR0(%r1) + lwz %r8, SSX_VOL_FAST_CTX_GPR8(%r1) + lwz %r9, SSX_VOL_FAST_CTX_GPR9(%r1) + lwz %r10, SSX_VOL_FAST_CTX_GPR10(%r1) + lwz %r11, SSX_VOL_FAST_CTX_GPR11(%r1) + lwz %r12, SSX_VOL_FAST_CTX_GPR12(%r1) + + lwz %r1, 0(%r1) + + .endm + + ## ------------------------------------------------------------ + ## Save/restore the non-volatile context on the stack + ## + ## 2 Instructions, 19 Loads/Stores + ## ------------------------------------------------------------ + + .macro _ssx_non_vol_ctx_push + + stwu %r1, -SSX_NON_VOL_CTX_SIZE(%r1) + stmw %r14, SSX_NON_VOL_CTX_GPR14(%r1) + + .endm + + + .macro _ssx_non_vol_ctx_pop + + lmw %r14, SSX_NON_VOL_CTX_GPR14(%r1) + lwz %r1, 0(%r1) + + .endm + +#else /* __ASSEMBLER__ */ + +/// SSX thread context layout as a C structure. +/// +/// This is the structure of the stack area pointed to by +/// thread->saved_stack_pointer when a thread is fully context-switched out. + +typedef struct { + + uint32_t r1_nv; + uint32_t link_nv; + uint32_t r14; + uint32_t r15; + uint32_t r16; + uint32_t r17; + uint32_t r18; + uint32_t r19; + uint32_t r20; + uint32_t r21; + uint32_t r22; + uint32_t r23; + uint32_t r24; + uint32_t r25; + uint32_t r26; + uint32_t r27; + uint32_t r28; + uint32_t r29; + uint32_t r30; + uint32_t r31; + uint32_t r1_vf; + uint32_t link_vf; + uint32_t r0; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t r12; + uint32_t xer; + uint32_t ctr; + uint32_t srr0; + uint32_t srr1; + uint32_t srr2; + uint32_t srr3; + uint32_t r1; + uint32_t link_fast; + uint32_t r3; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t cr; + uint32_t lr; + uint32_t usprg0; + +} SsxThreadContext; + + +/// SSX thread context of an interrupted thread (full-mode handler) +/// +/// When a thread is interrupted by a full-mode interrupt handler, this is the +/// layout of the stack area pointed to by either __ssx_saved_sp_noncritical +/// or __ssx_saved_sp_critical. + +typedef struct { + + uint32_t r1_vf; + uint32_t link_vf; + uint32_t r0; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + uint32_t r12; + uint32_t xer; + uint32_t ctr; + uint32_t srr0; + uint32_t srr1; + uint32_t srr2; + uint32_t srr3; + uint32_t r1; + uint32_t link_fast; + uint32_t r3; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t cr; + uint32_t lr; + uint32_t usprg0; + +} SsxThreadContextFullIrq; + + +/// SSX thread context of an interrupted thread (fast-mode handler) +/// +/// When a thread is interrupted by a fast-mode interrupt handler, this is the +/// layout of the stack area pointed to by R1 - unless the fast-mode interrupt +/// handler extends the stack. + +typedef struct { + + uint32_t r1; + uint32_t link_fast; + uint32_t r3; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t cr; + uint32_t lr; + uint32_t usprg0; + +} SsxThreadContextFastIrq; + +#endif /* __ASSEMBLER__ */ + +#endif /* __PPC405_CONTEXT_H__ */ + + diff --git a/src/ssx/ppc405/ppc405_core.c b/src/ssx/ppc405/ppc405_core.c new file mode 100755 index 0000000..5df0967 --- /dev/null +++ b/src/ssx/ppc405/ppc405_core.c @@ -0,0 +1,183 @@ +// $Id: ppc405_core.c,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_core.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_core.c +/// \brief The final bits of SSX runtime code required to complete the PPC405 +/// port. +/// +/// The entry points in this file are considered 'core' routines that will +/// always be present during runtime in any SSX application. + +#define __PPC405_CORE_C__ + +#include "ssx.h" + +/// Get the 64-bit timebase following the PowerPC protocol +/// +/// Note that the only way to guarantee that the value returned is the value +/// \e right \e now is to call this API from a critical section. + +SsxTimebase +ssx_timebase_get(void) +{ + Uint64 tb; + uint32_t high; + + do { + tb.word[0] = mftbu(); + tb.word[1] = mftb(); + high = mftbu(); + } while (high != tb.word[0]); + + return tb.value; +} + + +/// Set the 64-bit timebase in an SSX_CRITICAL critical section +/// +/// It is assumed that the caller knows what they are doing; e.g., is aware of +/// what may happen when time warps as a result of this call. + +void +ssx_timebase_set(SsxTimebase timebase) +{ + SsxMachineContext ctx; + Uint64 tb; + + tb.value = timebase; + + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + + mttbl(0); + mttbu(tb.word[0]); + mttbl(tb.word[1]); + + ssx_critical_section_exit(&ctx); +} + + +/// Enable interrupt preemption +/// +/// This API can only be called from an interrupt context. Threads will +/// always be preempted by interrupts unless they explicitly disable +/// interrupts with the \c ssx_interrupt_disable() API. It is legal to call +/// this API redundantly. +/// +/// Be careful when enabling interrupt handler preemption that the interrupt +/// being handled does not/can not trigger again, as this could rapidly lead +/// to stack overflows. +/// +/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_ILLEGAL_CONTEXT The API call was not made from an interrupt +/// context. + +int +ssx_interrupt_preemption_enable() +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_UNLESS_ANY_INTERRUPT_CONTEXT(); + } + + if (__ssx_kernel_context_noncritical_interrupt()) { + wrteei(1); + } else { + or_msr(MSR_CE); + } + + return SSX_OK; +} + + +/// Disable interrupt preemption +/// +/// This API can only be called from an interrupt context. Threads will +/// always be preempted by interrupts unless they explicitly disable +/// interrupts with the \c ssx_interrupt_disable() API. It is legal to call +/// this API redundantly. +/// +/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_ILLEGAL_CONTEXT The API call was not made from an interrupt +/// context. + +int +ssx_interrupt_preemption_disable() +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_UNLESS_ANY_INTERRUPT_CONTEXT(); + } + + if (__ssx_kernel_context_noncritical_interrupt()) { + wrteei(0); + } else { + andc_msr(MSR_CE); + } + + return SSX_OK; +} + + +#if SSX_TIMER_SUPPORT + +// The tickless kernel timer mechanism for PPC405 +// +// This routine must be called from an SSX_NONCRITICAL critical section. +// +// Tickless timeouts are provided by programming the PIT timer based on when +// the next timeout will occur. If the timeout is for the end of time there's +// nothing to do - SSX does not use auto-reload mode so no more PIT interrupts +// will be arriving. Otherwise, if the timeout is longer than the 32-bit PIT +// timer can handle, we simply schedule the timeout for 2**32 - 1 and +// __ssx_timer_handler() will keep rescheduling it until it finally occurs. +// If the \a timeout is in the past, we schedule the PIT interrupt for 1 tick +// in the future in accordance with the SSX specification. + +void +__ssx_schedule_hardware_timeout(SsxTimebase timeout) +{ + SsxTimebase now; + uint32_t pit; + + if (timeout != SSX_TIMEBASE_MAX) { + + now = ssx_timebase_get(); + + if (timeout <= now) { + pit = 1; + } else if ((timeout - now) > 0xffffffff) { + pit = 0xffffffff; + } else { + pit = timeout - now; + } + + mtspr(SPRN_PIT, pit); + } +} + + +// Cancel the PPC405 tickless kernel timeout +// +// This routine must be called from an SSX_NONCRITICAL critical section. SSX +// does not use auto-reload mode of the PIT, so simply writing the PIT with 0 +// effectively cancels the timer. + +void +__ssx_cancel_hardware_timeout() +{ + mtspr(SPRN_PIT, 0); +} + + +#endif /* SSX_TIMER_SUPPORT */ + +#undef __PPC405_CORE_C__ diff --git a/src/ssx/ppc405/ppc405_dcr.h b/src/ssx/ppc405/ppc405_dcr.h new file mode 100755 index 0000000..1f389bf --- /dev/null +++ b/src/ssx/ppc405/ppc405_dcr.h @@ -0,0 +1,55 @@ +#ifndef __PPC405_DCR_H__ +#define __PPC405_DCR_H__ + +// $Id: ppc405_dcr.h,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_dcr.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_dcr.h +/// \brief Everything related to PPC405-specific DCRs +/// +/// DCRs are chip-specific. This file only defines DCR access methods; DCR +/// numbers will be defined by chip-specific headers. + +/// Move From DCR +/// +/// Note that \a dcrn must be a compile-time constant. + +#define mfdcr(dcrn) \ + ({uint32_t __value; \ + asm volatile ("mfdcr %0, %1" : "=r" (__value) : "i" (dcrn)); \ + __value;}) + + +/// Move to DCR +/// +/// Note that \a dcrn must be a compile-time constant. + +#define mtdcr(dcrn, value) \ + ({uint32_t __value = (value); \ + asm volatile ("mtdcr %0, %1" : : "i" (dcrn), "r" (__value)); \ + }) + + +/// Read-Modify-Write a DCR with OR (Set DCR bits) +/// +/// Note that \a dcrn must be a compile-time constant. This operation is only +/// guaranteed atomic in a critical section. + +#define or_dcr(dcrn, x) \ + mtdcr(dcrn, mfdcr(dcrn) | (x)) + + +/// Read-Modify-Write a DCR with AND complement (Clear DCR bits) +/// +/// Note that \a dcrn must be a compile-time constant. This operation is only +/// guaranteed atomic in a critical section. + +#define andc_dcr(dcrn, x) \ + mtdcr(dcrn, mfdcr(dcrn) & ~(x)) + +#endif /* __PPC405_DCR_H__ */ diff --git a/src/ssx/ppc405/ppc405_exceptions.S b/src/ssx/ppc405/ppc405_exceptions.S new file mode 100755 index 0000000..c8be2e3 --- /dev/null +++ b/src/ssx/ppc405/ppc405_exceptions.S @@ -0,0 +1,832 @@ +// $Id: ppc405_exceptions.S,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_exceptions.S,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_exceptions.S +/// \brief PPC405 exception vector area. +/// +/// The PowerPC exception vector area has many small and large 'holes' in the +/// SSX implementation. These are due to numerous unhandled exceptions and +/// unimplemented exceptions in the exception vector area that comprises 8KB +/// in the 405. SSX interrupt handling and other code is 'packed' into these +/// holes to reduce the effective code footprint of SSX. The packing is done +/// (hopefully) on a reasonable basis - we haven't tried to squeeze every last +/// byte by chopping up routines willy-nilly and stitching them together with +/// random branches - but some fragmentation has occurred in the interrupt +/// handling code. +/// +/// To facilitate the packing, the exception vector area is divided into 5 ELF +/// sections (addresses are offsets into the exception area) +/// +/// .vectors_0000 - Empty section for adding image header +/// +/// .vectors_0100 - From 0x0100 to 0x0bff. The beginning of the table through +/// the large space prior to the system call vector. +/// +/// .vectors_0c00 - From 0x0c00 to 0x0eff. This is a moderately large area +/// after the system call vector. +/// +/// .vectors_0f00 - From 0x0f00 to 0x1fff. From the APU Unavailable vector +/// through the major 3.5K hole above the Debug vector. +/// +/// .vectors_2000 - From 0x2000 to 0x2003 - branch to the Debug handler. +/// +/// The exception vector area must be aligned on a 64KB boundary. +/// +/// Note that PgP mainstore boot and interrupt controller handling is +/// currently hard-coded into this file - but it can easily be generalized if +/// a port to another environment is required, assuming the new environment +/// has something similar to a PgP or 405 ASIC interrupt controller. +/// +/// \cond + + .nolist +#include "ssx.h" + .list + +### **************************************************************************** +### .vectors_0000 - Empty section ( Image header will be placed in this section +### from the linker command file ) +### **************************************************************************** + + .section .vectors_0000, "a", @progbits + .global __vectors + .global __vectors_0000 +__vectors: +__vectors_0000: + +### **************************************************************************** +### .vectors_0100 +### **************************************************************************** + .section .vectors_0100, "ax", @progbits + + .global __vectors_0100 + +__vectors_0100: + + ############################################################ + # 0x0100 : Critical Interrupt + ############################################################ + +__critical_interrupt: + + ## The critical interrupt handler entry point is re-entrant - A handler + ## may allow preemption, which could cause another entry here. + + ## Entry invariants: + ## 1. Critical interupts are disabled; + ## 2. The SP points to a thread stack, the non-critical stack or + ## critical stack + + ## Since fast-mode handlers can not use SSX services or alter the + ## machine context, the exit of a fast mode handler is a simple RF(C)I. + + ## Begin by pushing the fast context on the stack. + + _ssx_fast_ctx_push SSX_CRITICAL + + ## Load critical status 0 and the handler array base address. Check + ## for interrupts pending in status register 0 while the IRQ is + ## computed and R5 is loaded with the critical flag. + + _lwzi %r3, %r3, OCB_OCISR0 + _liw %r6, __ppc405_irq_handlers + cmpwi %r3, 0 + cntlzw %r4, %r3 + li %r5, SSX_CRITICAL + bne+ critical_irq_found + + ## No IRQ pending in interrupt set 0. Try set 1. + + _lwzi %r3, %r3, OCB_OCISR1 + cmpwi %r3, 0 + cntlzw %r4, %r3 + addi %r4, %r4, 32 + beq- critical_phantom + + ## An active IRQ was found. At entry here R6 has the handler table + ## base address, R4 has the IRQ number, and R5 has the critical + ## flag. The IRQ is converted into a pointer to an 8-byte handler + ## structure, and the handler is dispatched. The call is made with the + ## parameters: + + ## R3 = private + ## R4 = irq + ## R5 = SSX_CRITICAL + +critical_irq_found: + + _save_update_kernel_context SSX_CRITICAL, %r4, %r7 + slwi %r3, %r4, 3 + lwzux %r7, %r6, %r3 + lwz %r3, 4(%r6) + mtlr %r7 + blrl + + ## Pop the stack/RFCI when (if) it returns here. + +fast_exit_critical: + + _ssx_fast_ctx_pop_exit SSX_CRITICAL + + ## This is a phantom interrupt - we got interrupted but no status bits + ## are set. The interrupt is marked as #64. The register used for the + ## handler table address (R6) is set to the special structure for the + ## phantom interrupt, with it's address adjusted to make it appear to + ## be the 64th entry in the table. + +critical_phantom: + + _liw %r6, __ppc405_phantom_irq + subi %r6, %r6, (64 * 8) + b critical_irq_found + + + ############################################################ + # 0x0200 : Machine Check, Data or Instruction + ############################################################ + + .org __vectors_0100 + 0x0100 +__machine_check: + + PPC405_MACHINE_CHECK_HANDLER + + .org __machine_check + 0x20 + + .global __ssx_irq_fast2full +__ssx_irq_fast2full: + + ## Convert a fast-mode to a full-mode interrupt by saving the + ## (volatile - fast) context, and switching to the appropriate system + ## stack. + + ## Entry invariants: + ## 1. The SP/stack must be exactly as it was when the fast-mode + ## handler was entered. + ## 2. No changes have been made to the MSR - the interrupt level must + ## remain disabled. + ## 3. The handler owns the fast context and has not modified the other + ## register context. This routine can only use the (volatile - + ## fast) register context. + + ## 41 (linear) instructions plus alignmenmt + + ## Start by pushing the (volatile - fast) context. Technically we also + ## need to save the CR as our contract with the handler is not to + ## disturb any of its register state. + + _ssx_vol_fast_ctx_push SSX_IRQ_CONTEXT + mfcr %r12 + + ## USPRG0 tells whether this is a critical or non-critical interrupt. + ## The high-order 8 bits of USPRG0 counts critical interrupt nesting, + ## and the SSX preemption rules guarantee that if the count is > 0 then + ## we are in a critical handler. + + mfusprg0 %r8 + extrwi. %r9, %r8, 8, 0 + beq fast2full_noncritical + + ## If the critical interrupt count is > 1, we are already in a + ## nested critical interrupt, so we're already on the critical stack + ## and there's nothing left to do. + + cmpwi %r9, 1 + bne 1f + + ## Otherwise, save the current stack pointer and switch to the critical + ## stack. + + _stwsd %r1, __ssx_saved_sp_critical + _lwzsd %r1, __ssx_critical_stack + + ## Restore the CR and return to the now full-mode handler. + +1: + mtcr %r12 + blr + + ## Non-critical interrupts are handled analogously to the above, + ## except that bits 8:15 of R7 are the non-critical + ## count. At entry here the (volatile - fast) context has been pushed, + ## R8 has USPRG0 and R12 contains the saved CR. + + ## Note that it would violate a kernel/API invariant if this routine + ## were entered from outside an interrupt context. + + .cache_align +fast2full_noncritical: + + extrwi %r9, %r8, 8, 8 + cmpwi %r9, 1 + bne 1f + + _stwsd %r1, __ssx_saved_sp_noncritical + _lwzsd %r1, __ssx_noncritical_stack + +1: + + .if (SSX_ERROR_CHECK_KERNEL | SSX_ERROR_CHECK_API) + cmpwi %r9, 0 + bne 2f + _ssx_panic PPC405_IRQ_FAST2FULL_INVARIANT +2: + .endif + + mtcr %r12 + blr + + + ############################################################ + # 0x0300 : Data Storage Interrupt + ############################################################ + + .org __vectors_0100 + 0x0200 +__data_storage: + + PPC405_DATA_STORAGE_HANDLER + + .org __data_storage + 0x20 + + .global __ssx_irq_full_mode_exit +__ssx_irq_full_mode_exit: + + ## Exit a full-mode handler. + + ## Entry invariants: + ## 1. The SP/stack must be in exactly the same state it was left in at + ## the exit of __ssx_irq_fast2full. + ## 2. It is assumed the the preemption rules of SSX have been followed + ## - in particular that critical handlers have not enabled + ## non-critical interrupts. + + ## We can freely modify the volatile context here - the handler is done + ## and we will restore the interrupted volatile context. + + ## 22 linear instructions + + ## If the critical count is non-zero, then the SSX preemption rules + ## guarantee that we are exiting from a critical interrupt + ## handler. This test is safe to make even if critical interrupts are + ## enabled, because the variable is set exactly once in a critical + ## section. + + mfusprg0 %r3 + extrwi. %r4, %r3, 8, 0 + beq full_exit_noncritical + + ## The context restore must be done from a critical section, in case + ## the handler enabled preemption. + + _ssx_critical_section_enter SSX_CRITICAL, %r5, %r6 + + ## If the critical count (R4) is > 1 then this is a nested interrupt + ## and we can simply pop the context and RFCI. + + cmpwi %r4, 1 + bne full_exit_critical + + ## Otherwise, restore the saved stack pointer before popping and RFCI. + + _lwzsd %r1, __ssx_saved_sp_critical + +full_exit_critical: + _ssx_vol_fast_ctx_pop SSX_IRQ_CONTEXT, SSX_CRITICAL + b fast_exit_critical + + + ############################################################ + # 0x0400 : Instruction Storage Interrupt + ############################################################ + + .org __vectors_0100 + 0x0300 +__instruction_storage: + + PPC405_INSTRUCTION_STORAGE_HANDLER + + .org __instruction_storage + 0x20 + + ## The idle thread has no permanent register context. The idle thread + ## entry point is re-entered whenever the idle thread is scheduled. + + .global __ssx_idle_thread + .global __ssx_idle_thread_from_bootloader + +__ssx_idle_thread: + + ## The idle thread 'uses' the non-critical stack. Any register context + ## pushed here is redundant and is wiped out/ignored every time the + ## idle thread is re-scheduled. + + ## The idle thread simply establishes a default machine context and + ## enters the wait-enable state. The idle thread is always entered + ## with non-critical interrupts disabled. + ## + ## The kernel context is initialized to indicate that the idle thread + ## is running - the idle thread priority is SSX_THREADS, and the + ## 'thread-mode' bit is asserted as well. + ## + ## This loop can also be called from the SSX bootloader if main() + ## returns - in which case we don't muck with the USPRG0 or the stack + ## pointer. + + li %r3, (SSX_THREADS | PPC405_THREAD_MODE) + mtusprg0 %r3 + _lwzsd %r1, __ssx_noncritical_stack + +__ssx_idle_thread_from_bootloader: + + li %r3, SSX_THREADS + SSX_TRACE_THREAD_SWITCH %r3, %r4 + _lwzsd %r3, __ssx_thread_machine_context_default + _oriwa %r3, %r3, MSR_WE + mtmsr %r3 + b . + + ## ssx_halt() is implemented on the PPC405 by disabling all + ## interrupts, forcing external debug mode, and executing a trap. A + ## 0x0 word appears after the trap instruction similar to the default + ## SSX_PANIC macro. The caller may also call ssx_halt() with + ## parameters which will appear in R3, R4, etc. In the Simics + ## environment we use the Simics 'trap' since Simics does not handle + ## the PPC405 TRAP instruction correctly. + + .global ssx_halt +ssx_halt: + li %r31, 0 + mtmsr %r31 + isync + _liwa %r31, (DBCR0_EDM | DBCR0_TDE) + mtdbcr0 %r31 + isync +#if SIMICS_ENVIRONMENT + rlwimi 1, 1, 0, 0, 0 +#else + trap +#endif + .long 0 + + ############################################################ + # 0x0500 : External Interrupt + ############################################################ + + .org __vectors_0100 + 0x0400 +__external_interrupt: + + ## The non-critical interrupt handler entry point is re-entrant - A + ## handler may allow preemption, which could cause another entry here. + + ## Entry invariants: + ## 1. Non-critical interupts are disabled; + ## 2. The SP points to a thread stack or the non-critical stack. + + ## Since fast-mode handlers can not use SSX services or alter the + ## machine context, the exit of a fast mode handler is a simple RF(C)I. + + ## Begin by pushing the fast context on the current stack. + + _ssx_fast_ctx_push SSX_NONCRITICAL + + ## Load noncritical status 0 and the handler array base address. Check + ## for interrupts pending in status register 0 while the IRQ is + ## computed and R5 is loaded with the noncritical flag. + + _lwzi %r3, %r3, OCB_ONISR0 + _liw %r6, __ppc405_irq_handlers + cmpwi %r3, 0 + cntlzw %r4, %r3 + li %r5, SSX_NONCRITICAL + bne+ noncritical_irq_found + + ## No IRQ pending in interrupt set 0. Try set 1. + + _lwzi %r3, %r3, OCB_ONISR1 + cmpwi %r3, 0 + cntlzw %r4, %r3 + addi %r4, %r4, 32 + beq- noncritical_phantom + + ## An active IRQ was found. At entry here R6 has the handler table + ## base address, R4 has the IRQ number, and R5 has the noncritical + ## flag. The IRQ is converted into a pointer to an 8-byte handler + ## structure, and the handler is dispatched. The call is made with the + ## parameters: + + ## R3 = private + ## R4 = irq + ## R5 = SSX_NONCRITICAL + +noncritical_irq_found: + + _save_update_kernel_context SSX_NONCRITICAL, %r4, %r7 + slwi %r3, %r4, 3 + lwzux %r7, %r6, %r3 + lwz %r3, 4(%r6) + mtlr %r7 + blrl + + ## Pop the stack/RFI when (if) it returns here. + +fast_exit_noncritical: + + _ssx_fast_ctx_pop_exit SSX_NONCRITICAL + + ## This is a phantom interrupt - we got interrupted but no status bits + ## are set. The interrupt is marked as #64. The register used for the + ## handler table address (R6) is set to the special structure for the + ## phantom interrupt, with it's address adjusted to make it appear to + ## be the 64th entry in the table. + +noncritical_phantom: + + _liw %r6, __ppc405_phantom_irq + subi %r6, %r6, (64 * 8) + b noncritical_irq_found + + ############################################################ + # 0x0600 : Alignment Exception + ############################################################ + + .org __vectors_0100 + 0x0500 +__alignment_exception: + + PPC405_ALIGNMENT_HANDLER + + .org __alignment_exception + 0x20 +pit_handler: + + ## The portable timer handler of SSX a full-mode handler with the prototype: + ## void (*ssx_timer_handler)(void). + ## + ## To support the portable specification, the kernel clears the + ## interrupt by writing the PIS back into the TSR before calling the + ## handler. SSX does not use the PIT in auto-reload mode - it is + ## tickless - so the interrupt will not fire again until reprogrammed + ## by the timer handler. The timer handler does not take any arguments. + + ## 21 instructions + + _ssx_fast_ctx_push SSX_NONCRITICAL + li %r3, PPC405_IRQ_PIT + _save_update_kernel_context SSX_NONCRITICAL, %r3, %r4 + + _liwa %r3, TSR_PIS + mttsr %r3 + isync + + _ssx_irq_fast2full __ssx_timer_handler + + + ############################################################ + # 0x0700 : Program Interrupt + ############################################################ + + .org __vectors_0100 + 0x0600 +__program_interrupt: + + PPC405_PROGRAM_HANDLER + + .org __program_interrupt + 0x20 + + ## Exiting a full-mode non-critical handler is more complex than the + ## critical case, because the handler may have made a new + ## highest-priority thread runnable and we may need to go through a + ## delayed scheduling step. + + ## Note that the idle thread is treated as a special case. The idle + ## thread has no permanent register context. To avoid having to + ## allocate a stack area for the idle thread, the idle thread + ## 'uses' the non-critical stack. When the idle thread is interrupted + ## the (redundant) context is pushed, but is then effectively lost. + ## Whenever we restore the idle thread we simply reenter the idle + ## thread entry point. + + ## At entry: + ## 1. R3 holds the value of USPRG0 (__SsxKernelContext) + + ## 33 linear instructions. + +full_exit_noncritical: + + ## Enter a critical section for the return from interrupt, in the event + ## that the handler enabled preemption. + + _ssx_critical_section_enter SSX_NONCRITICAL, %r4, %r5 + + ## If the non-critical count is > 1 then this is a nested interrupt + ## and we can simply pop the context and RFI. Note that it would + ## violate a kernel/API invariant if this routine were entered from + ## outside an interrupt context (interrupt level == 0). + + extrwi. %r4, %r3, 8, 8 + + .if (SSX_ERROR_CHECK_KERNEL | SSX_ERROR_CHECK_API) + bne 1f + _ssx_panic PPC405_IRQ_FULL_EXIT_INVARIANT +1: + .endif + + cmpwi %r4, 1 + bne exit_noncritical_without_switch + + ## Otherwise, restore the saved stack pointer and continue. + + _lwzsd %r1, __ssx_saved_sp_noncritical + + ## If we are not in thread mode (i.e., we took an interrupt in an + ## interupt-only configuration of SSX or after ssx_initialize() but + ## before ssx_start_threads) simply pop the context and RFI - in this + ## case we'll most likely be returning to main() or the non-thread-mode + ## idle thread. + + andi. %r4, %r3, PPC405_THREAD_MODE + beq exit_noncritical_without_switch + + ## Now, check for a delayed context switch. If none is pending, we can + ## exit (after a check for the idle thread special case). + + _lwzsd %r3, __ssx_delayed_switch + cmpwi %r3, 0 + bne noncritical_switch + + _lwzsd %r3, __ssx_current_thread + cmpwi %r3, 0 + beq __ssx_idle_thread + +exit_noncritical_without_switch: + _ssx_vol_fast_ctx_pop SSX_IRQ_CONTEXT, SSX_NONCRITICAL + b fast_exit_noncritical + + ## The non-critical interrupt activated a delayed context switch. The + ## C-level code has taken care of the scheduling decisions - we simply + ## need to implement them here. + +noncritical_switch: + + ## Clear the delayed switch flag and go to the context switch code to + ## finish the switch. + + li %r3, 0 + _stwsd %r3, __ssx_delayed_switch + + b thread_save_non_volatile_and_switch + + + ############################################################ + # 0x0800 : FPU Unavailable + ############################################################ + + .org __vectors_0100 + 0x0700 +__fpu_unavailable: + + PPC405_FPU_UNAVAILABLE_HANDLER + + .org __fpu_unavailable + 0x20 + + + ## Exit traces are moved here because the code area (0x100 bytes) + ## reserved for individual interrupts is overflowing when tracing is + ## enabled. This is kind of a hack: We know that this trace only + ## occurs when we're about to exit the fast context, at a place + ## where we can use any of the fast registers. + +__ssx_trace_critical_irq_exit: + SSX_TRACE_CRITICAL_IRQ_EXIT %r3, %r4 + blr + +__ssx_trace_noncritical_irq_exit: + SSX_TRACE_NONCRITICAL_IRQ_EXIT %r3, %r4 + blr + + ## >>>>>>>>>> Pack .vectors_0100 here. Room for ~900 bytes. <<<<<<<<<< + +### **************************************************************************** +### .vectors_0c00 +### **************************************************************************** + + .section .vectors_0c00, "ax", @progbits + .global __vectors_0c00 +__vectors_0c00: + + ############################################################ + # 0x0c00 : System Call + ############################################################ + + .org __vectors_0c00 + 0x0 + .global __ssx_next_thread_resume + +__system_call: + + ## The system call exception is used by SSX as a handy way to start a + ## context switch, as the continuation address and MSR of the thread to + ## be swapped out are saved in SRR0 and SRR1. + + ## Non-critical interrupts are disabled at entry. + + ## Note that the system call exception begins a large free area + ## so there is plenty of room for the context switch code. + + ## Begin by saving the volatile context of the current thread. + + _ssx_fast_ctx_push SSX_NONCRITICAL + _ssx_vol_fast_ctx_push SSX_THREAD_CONTEXT + +thread_save_non_volatile_and_switch: + + ## Finish the thread context save by pushing the non-volatile context + ## and saving the resulting stack pointer in the thread structure. If + ## the current thread is the idle thread this step is bypassed. + + ## This symbol is also used as an entry point by the non-critical + ## interrupt handler - non-critical interrupts are disabled here. + + _lwzsd %r3, __ssx_current_thread + cmpwi %r3, 0 + beq __ssx_next_thread_resume + + _ssx_non_vol_ctx_push + stw %r1, SSX_THREAD_OFFSET_SAVED_STACK_POINTER(%r3) + + ## The next thread becomes the current thread, and we switch to its + ## stack - unless the new thread is the idle thread, in which case it + ## (the idle thread) is simply resumed. + +__ssx_next_thread_resume: + + _lwzsd %r3, __ssx_next_thread + _stwsd %r3, __ssx_current_thread + + cmpwi %r3, 0 + beq __ssx_idle_thread + + lwz %r1, SSX_THREAD_OFFSET_SAVED_STACK_POINTER(%r3) + + ## Restore the thread context and resume the new thread. The kernel + ## context in thread mode is simply the thread priority OR'ed with the + ## thread-mode flag. All other fields are cleared. + + _ssx_non_vol_ctx_pop + _ssx_vol_fast_ctx_pop SSX_THREAD_CONTEXT, SSX_NONCRITICAL + + _lbzsd %r3, __ssx_next_priority + SSX_TRACE_THREAD_SWITCH %r3, %r4 + ori %r3, %r3, PPC405_THREAD_MODE + mtusprg0 %r3 + + _ssx_fast_ctx_pop + rfi + + ## >>>>>>>> Pack .vectors_0c00 here - room for ~500 bytes <<<<<<< + +### **************************************************************************** +### .vectors_0f00 +### **************************************************************************** + + .section .vectors_0f00, "ax", @progbits + .global __vectors_0f00 +__vectors_0f00: + + ############################################################ + # 0x0f20 : APU Unavailable + ############################################################ + + .org __vectors_0f00 + 0x20 # 0x0f20 +__apu_unavailable: + + PPC405_APU_UNAVAILABLE_HANDLER + + .org __vectors_0f00 + 0x40 # 0x0f40 + +fit_handler: + + ## The FIT handler is user defined, and is a fast-mode handler. By + ## convention the kernel clears the interrupt by writing the FIS back + ## into the TSR. + + _ssx_fast_ctx_push SSX_NONCRITICAL + + _lwzsd %r3, __ppc405_fit_arg + li %r4, PPC405_IRQ_FIT + li %r5, SSX_NONCRITICAL + + _save_update_kernel_context SSX_NONCRITICAL, %r4, %r6 + + _liwa %r6, TSR_FIS + mttsr %r6 + isync + + _lwzsd %r6, __ppc405_fit_routine + mtlr %r6 + blrl + + b fast_exit_noncritical + + + ############################################################ + # 0x10x0 : PIT, FIT and Watchdog Interrupts + ############################################################ + + .org __vectors_0f00 + 0x100 # 0x1000 +__pit_interrupt: + + b pit_handler + + .org __vectors_0f00 + 0x110 # 0x1010 +__fit_interrupt: + + b fit_handler + + .org __vectors_0f00 + 0x120 # 0x1020 +__watchdog_interrupt: + + ## Watchdog setup is described in the SSX Specification. + ## The kernel clears TSR[WIS] prior to calling the handler. + ## The watchdog handler is a critical, fast-mode handler. + + _ssx_fast_ctx_push SSX_CRITICAL + + _lwzsd %r3, __ppc405_watchdog_arg + li %r4, PPC405_IRQ_WATCHDOG + li %r5, SSX_CRITICAL + + _save_update_kernel_context SSX_CRITICAL, %r4, %r6 + + _liwa %r6, TSR_WIS + mttsr %r6 + isync + + _lwzsd %r6, __ppc405_watchdog_routine + mtlr %r6 + blrl + + b fast_exit_critical + + + ############################################################ + # 0x1100 : Data TLB Miss + ############################################################ + + .org __vectors_0f00 + 0x200 # 0x1100 +__data_tlb_miss: + + PPC405_DATA_TLB_MISS_HANDLER + + .org __data_tlb_miss + 0x20 +debug_handler: + + ## SSX does nothing upon reception of the debug interrupt other + ## than calling the handler (if non-0). The debug handler is a + ## fast-mode handler. + + _ssx_fast_ctx_push SSX_CRITICAL + + _lwzsd %r3, __ppc405_debug_arg + li %r4, PPC405_IRQ_DEBUG + li %r5, SSX_CRITICAL + + _save_update_kernel_context SSX_CRITICAL, %r4, %r6 + + _lwzsd %r6, __ppc405_debug_routine + cmpwi %r6, 0 + mtlr %r6 + beq debug_exit + blrl + +debug_exit: + b fast_exit_critical + + + ############################################################ + # 0x1200 : Instruction TLB Miss + ############################################################ + + .org __vectors_0f00 + 0x300 # 0x1200 +__instruction_tlb_miss: + + PPC405_INSTRUCTION_TLB_MISS_HANDLER + + .org __instruction_tlb_miss + 0x20 + + ## >>>>>> Pack .vectors_0f00 A huge hole here - ~3.5KB <<<<<< + +### **************************************************************************** +### .vectors_2000 +### **************************************************************************** + + .section .vectors_2000, "ax", @progbits + + .global __vectors_2000 +__vectors_2000: + + ############################################################ + # 0x2000 : Debug Interrupt + ############################################################ + +__debug_interrupt: + b debug_handler + +/// \endcond diff --git a/src/ssx/ppc405/ppc405_init.c b/src/ssx/ppc405/ppc405_init.c new file mode 100755 index 0000000..e818737 --- /dev/null +++ b/src/ssx/ppc405/ppc405_init.c @@ -0,0 +1,80 @@ +// $Id: ppc405_init.c,v 1.1.1.1 2013/12/11 21:03:26 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_init.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_init.c +/// \brief PPC405 initialization routines +/// +/// The entry points in this file are routines that are typically used during +/// initialization, and their code space could be deallocated and recovered if +/// no longer needed by the application after initialization. + +#include "ssx.h" + +// Note that __ppc405_system_setup() is called from the SSX bootloader early +// in the initialization, at a point before the aplication has enabled +// critical or external interruts. + +void +__ppc405_system_setup() +{ + SsxIrqId irq; + + // Initialize the interrupt vectors. + + for (irq = 0; irq < PPC405_IRQS; irq++) { + __ppc405_irq_handlers[irq].handler = __ppc405_default_irq_handler; + __ppc405_irq_handlers[irq].arg = 0; + } + + __ppc405_phantom_irq.handler = __ppc405_phantom_irq_handler; + __ppc405_phantom_irq.arg = 0; + + // Initialize special interrupt handlers + + __ppc405_fit_routine = __ppc405_default_irq_handler; + __ppc405_fit_arg = 0; + + __ppc405_watchdog_routine = __ppc405_default_irq_handler; + __ppc405_watchdog_arg = 0; + + __ppc405_debug_routine = __ppc405_default_irq_handler; + __ppc405_debug_arg = 0; + + // Enable the PIT interrupt, but not auto-reload mode. Clear the status + // of all timers for good measure. + + andc_spr(SPRN_TCR, TCR_ARE); + or_spr(SPRN_TCR, TCR_PIE); + + or_spr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS); + + // Call system-specific setup + +#ifdef CHIP_PGP + void __pgp_setup(); + __pgp_setup(); +#endif + +} + + +// Set the timebase using the PowerPC protocol. + +void +__ssx_timebase_set(SsxTimebase t) +{ + Uint64 tb; + + tb.value = t; + + mttbl(0); + mttbu(tb.word[0]); + mttbl(tb.word[1]); +} + + diff --git a/src/ssx/ppc405/ppc405_irq.h b/src/ssx/ppc405/ppc405_irq.h new file mode 100755 index 0000000..d85e9ce --- /dev/null +++ b/src/ssx/ppc405/ppc405_irq.h @@ -0,0 +1,342 @@ +#ifndef __PPC405_IRQ_H__ +#define __PPC405_IRQ_H__ + +// $Id: ppc405_irq.h,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_irq.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_irq.h +/// \brief PPC405 interrupt handling for SSX +/// +/// Interrupt handling protocols and interrupt controller programming are +/// inherently non-portable, however SSX defines APIs that may be useful among +/// different machines. +/// +/// The interrupt controllers in PPC405 ASICS and PGP allow interrupts to be +/// programmed as critical or non-critical, with programmable polarity and +/// edge or level sensitivity. + + +// Define pseudo-IRQ numbers for PPC405 built-in interrupts. These numbers +// will appear in bits 16:23 of USPRG0 (__SsxKernelContext) when the handlers +// are active, and are also passed as the second argument of the handlers when +// they are invoked. + +#define PPC405_IRQ_PIT 0x80 +#define PPC405_IRQ_FIT 0x81 +#define PPC405_IRQ_WATCHDOG 0x82 +#define PPC405_IRQ_DEBUG 0x83 + +// These are suggested values to use for the IRQ in the __SsxKernelContext if +// the application defines handlers for any of the 'unhandled exceptions'. + +#define PPC405_EXC_MACHINE_CHECK 0x90 +#define PPC405_EXC_DATA_STORAGE 0x91 +#define PPC405_EXC_INSTRUCTION_STORAGE 0x92 +#define PPC405_EXC_ALIGNMENT 0x93 +#define PPC405_EXC_PROGRAM 0x94 +#define PPC405_EXC_FPU_UNAVAILABLE 0x95 +#define PPC405_EXC_APU_UNAVAILABLE 0x96 +#define PPC405_EXC_DATA_TLB_MISS 0x97 +#define PPC405_EXC_INSTRUCTION_TLB_MISS 0x98 + + +// Unhandled exceptions default to a kernel panic, but the application can +// override these definition. Note that the exception area only allocates 32 +// bytes (8 instructions) to an unhandled exception, so any redefinition +// would most likely be a branch to an application-defined handler. + +#ifndef PPC405_MACHINE_CHECK_HANDLER +#define PPC405_MACHINE_CHECK_HANDLER SSX_PANIC(0x0200) +#endif + +#ifndef PPC405_DATA_STORAGE_HANDLER +#define PPC405_DATA_STORAGE_HANDLER SSX_PANIC(0x0300) +#endif + +#ifndef PPC405_INSTRUCTION_STORAGE_HANDLER +#define PPC405_INSTRUCTION_STORAGE_HANDLER SSX_PANIC(0x0400) +#endif + +#ifndef PPC405_ALIGNMENT_HANDLER +#define PPC405_ALIGNMENT_HANDLER SSX_PANIC(0x0600) +#endif + +#ifndef PPC405_PROGRAM_HANDLER +#define PPC405_PROGRAM_HANDLER SSX_PANIC(0x0700) +#endif + +#ifndef PPC405_FPU_UNAVAILABLE_HANDLER +#define PPC405_FPU_UNAVAILABLE_HANDLER SSX_PANIC(0x0800) +#endif + +#ifndef PPC405_APU_UNAVAILABLE_HANDLER +#define PPC405_APU_UNAVAILABLE_HANDLER SSX_PANIC(0x0f20) +#endif + +#ifndef PPC405_DATA_TLB_MISS_HANDLER +#define PPC405_DATA_TLB_MISS_HANDLER SSX_PANIC(0x1100) +#endif + +#ifndef PPC405_INSTRUCTION_TLB_MISS_HANDLER +#define PPC405_INSTRUCTION_TLB_MISS_HANDLER SSX_PANIC(0x1200) +#endif + + +//////////////////////////////////////////////////////////////////////////// +// SSX API +//////////////////////////////////////////////////////////////////////////// + +#ifndef __ASSEMBLER__ + +/// An IRQ handler takes 3 arguments: +/// \arg \c arg - Private handler data installed by \c ssx_irq_setup() or +/// \c ssx_irq_handler_set(). +/// \arg \c irq - The IRQ id; to enable a generic handler to manipulate +/// its own interrupt status . +/// \arg \c priority - One of the values \c SSX_CRITICAL or \c +/// SSX_NONCRITICAL; to enable a generic handler to choose +/// a behavior appropriate for the interrupt priority. + +typedef void (*SsxIrqHandler)(void* arg, + SsxIrqId irq, + int priority); + +/// Declare a subroutine as an IRQ handler + +#define SSX_IRQ_HANDLER(f) void f(void *arg, SsxIrqId irq, int priority) + +int ssx_irq_setup(SsxIrqId irq, + int polarity, + int trigger); + +int ssx_irq_handler_set(SsxIrqId irq, + SsxIrqHandler handler, + void* arg, + int priority); + +void ssx_irq_enable(SsxIrqId irq); +void ssx_irq_disable(SsxIrqId irq); +void ssx_irq_statusclear(SsxIrqId irq); + +SSX_IRQ_HANDLER(__ppc405_default_irq_handler); +SSX_IRQ_HANDLER(__ppc405_phantom_irq_handler); + + +int +ppc405_fit_setup(int tcr_fp, SsxIrqHandler handler, void* arg); + + +/// The address of the optional FIT interrupt handler + +UNLESS__PPC405_IRQ_CORE_C__(extern) +volatile +SsxIrqHandler __ppc405_fit_routine; + + +/// The private data of the optional FIT interrupt handler + +UNLESS__PPC405_IRQ_CORE_C__(extern) +volatile +void* __ppc405_fit_arg; + + +int +ppc405_watchdog_setup(int tcr_wp, int tcr_wrc, + SsxIrqHandler handler, void* arg); + + +/// The address of the optional Watchdog interrupt handler + +UNLESS__PPC405_IRQ_CORE_C__(extern) +volatile +SsxIrqHandler __ppc405_watchdog_routine; + + +/// The private data of the optional Watchdog interrupt handler + +UNLESS__PPC405_IRQ_CORE_C__(extern) +volatile +void* __ppc405_watchdog_arg; + + +int +ppc405_debug_setup(SsxIrqHandler handler, void* arg); + + +/// The address of the optional Debug interrupt handler + +UNLESS__PPC405_IRQ_CORE_C__(extern) +volatile +SsxIrqHandler __ppc405_debug_routine; + + +/// The private data of the optional Watchdog interrupt handler + +UNLESS__PPC405_IRQ_CORE_C__(extern) +volatile +void* __ppc405_debug_arg; + + +// Note: Why SSX_IRQ_FAST2FULL (below) is implemented so strangely. +// +// I am adamant that I want to have a a macro in the 'C' environment to create +// these bridge functions. However the limitations of the C preprocessor and +// the intelligence of the GCC 'asm' facility consipre against a +// straightforward solution. The only way that I was able to find to get +// naked assembly code into the output stream is to use 'asm' with simple +// strings - I couldn't make it work with any kind of argument, as 'asm' would +// reinterpret the arguments and resulting assembler code in various ways. +// +// There is another alternative that I tried wherby I created a subroutine +// call and then filled in the subroutine body with 'asm' code. However, the +// subroutine wrapper that GCC creates only works for PowerPC fast-mode +// handlers if GCC is invoked with optimization, which ensures that the +// wrapper doesn't touch the stack pointer or other registers. True, we'll +// always use optimization, but I did not want to have to make this +// requirement for using this macro. + +/// This macro creates a 'bridge' handler that converts the initial fast-mode +/// IRQ dispatch into a call of a full-mode IRQ handler. The full-mode +/// handler is defined by the user (presumably as a \c C subroutine) and has +/// the same prototype (type SsxIrqHandler) as the fast handler. +/// +/// \param fast_handler This will be the global function name of the fast +/// IRQ handler created by this macro. This is the symbol +/// that should be passed in as the \a handler argument +/// of \c ssx_irq_setup() and \c ssx_irq_handler_set(). +/// +/// \param full_handler This is the name of the user-defined full-mode +/// handler which is invoked through this bridge. +/// +/// \e BUG \e ALERT : Beware of passing the \c full_handler to IRQ setup +/// APIs. This won't be caught by the compiler (because the \c full_handler +/// has the correct prototype) and will lead to nasty bugs. Always pass in +/// the \c fast_handler symbol to IRQ setup APIS. +/// +/// The code stream injected into the GCC assembler output in response to +/// +/// SSX_IRQ_FAST2FULL(fast_handler, full_handler) +/// +/// is (comments added for clarification) : +/// +/// \code +/// .text +/// .global fast_handler +/// .align 5 # Hard-coded PPC405 cache-line alignment +/// fast_handler = . # Can't macro expand LABEL: - this is equivalent +/// bl __ssx_irq_fast2full # The fast-mode to full-mode conversion sequence +/// bl full_handler +/// b __ssx_irq_full_mode_exit +/// \endcode +/// +/// The macro also declares the prototype of the fast handler: +/// +/// \code +/// SSX_IRQ_HANDLER(fast_handler); +/// \endcode +/// + +#define SSX_IRQ_FAST2FULL(fast_handler, full_handler) \ + SSX_IRQ_HANDLER(fast_handler); \ + __SSX_IRQ_FAST2FULL(.global fast_handler, fast_handler = ., bl full_handler) + +#define __SSX_IRQ_FAST2FULL(global, label, call) \ +asm(".text"); \ +asm(#global); \ +asm(".align 5"); \ +asm(#label); \ +asm("bl __ssx_irq_fast2full"); \ +asm(#call); \ +asm("b __ssx_irq_full_mode_exit"); + +#endif /* __ASSEMBLER__ */ + +// It's hard to be portable and get all of the definitions and headers in the +// correct order. We need to bring in the system IRQ header here. + +#ifdef CHIP_PGP +#include "pgp_irq.h" +#endif + +/// \page ppc405_irq_macros_page PPC405 SSX IRQ Assembler Macros +/// +/// +/// \section fast2full_asm Fast-Mode to Full-Mode Handler Conversion +/// +/// This macro produces the calling sequence required to convert a +/// fast-mode interrupt handler to a full-mode interrupt handler. The +/// full-mode handler is implemented by another subroutine. The +/// requirements for invoking this macro are: +/// +/// \li The stack pointer and stack must be exactly as they were when the +/// fast-mode handler was entered. +/// +/// \li No changes have been made to the MSR - the interrupt level must +/// remain disabled. +/// +/// \li The handler owns the fast context and has not modified the other +/// register context. The conversion process will not modify any +/// register in the fast context (other than the LR used for +/// subroutine linkage). +/// +/// The final condition above means that the \a full_handler will +/// begin with the fast-mode context exactly as it was (save for LR) +/// at conversion, including the contents of GPR3-7 (the first 5 +/// PowerPC ABI paramater passing registers) and the entire CR. +/// +/// Forms: +/// +/// \c _ssx_irq_fast2full \a full_handler +/// \cond + +#ifdef __ASSEMBLER__ + + .macro _ssx_irq_fast2full full_handler + bl __ssx_irq_fast2full + bl \full_handler + b __ssx_irq_full_mode_exit + .endm + +#endif /* __ASSEMBLER__ */ + +/// \endcond + +#ifndef __ASSEMBLER__ + + +/// This structure holds the interrupt handler routine addresses and private +/// data. Assembler code assumes the given structure layout, so any changes +/// to this structure will need to be reflected down into the interrupt +/// dispatch assembler code. + +typedef struct { + SsxIrqHandler handler; + void *arg; +} Ppc405IrqHandler; + + +/// Interrupt handlers for real (implemented interrupts) + +UNLESS__PPC405_IRQ_CORE_C__(extern) +Ppc405IrqHandler __ppc405_irq_handlers[PPC405_IRQS]; + + +/// The 'phantom interrupt' handler +/// +/// A 'phantom' interrupt occurs when the interrupt handling code in the +/// kernel is entered, but no interrupt is found pending in the controller. +/// This is considered a serious bug, as it indictates a short window +/// condition where a level-sensitive interrupt has been asserted and then +/// quickly deasserted before it can be handled. + +UNLESS__PPC405_IRQ_CORE_C__(extern) +Ppc405IrqHandler __ppc405_phantom_irq; + +#endif /* __ASSEMBLER__ */ + +#endif /* __PPC405_IRQ_H__ */ diff --git a/src/ssx/ppc405/ppc405_irq_core.c b/src/ssx/ppc405/ppc405_irq_core.c new file mode 100755 index 0000000..3cd7469 --- /dev/null +++ b/src/ssx/ppc405/ppc405_irq_core.c @@ -0,0 +1,49 @@ +// $Id: ppc405_irq_core.c,v 1.1.1.1 2013/12/11 21:03:26 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_irq_core.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_irq_core.c +/// \brief Core IRQ routines required of any PPC405 configuration of SSX +/// +/// This file is mostly only a placeholder - where 'extern inline' API +/// functions and 'extern' variables are realized. A couple of default +/// handlers are also installed here. The entry points in this file are +/// considered 'core' routines that will always be present at runtime in any +/// SSX application. + +#define __PPC405_IRQ_CORE_C__ + +#include "ssx.h" + +/// This function is installed by default for interrupts not explicitly set up +/// by the application. These interrupts should never fire. + +void +__ppc405_default_irq_handler(void *arg, + SsxIrqId irq, + int critical) +{ + SSX_PANIC(PPC405_DEFAULT_IRQ_HANDLER); +} + + +/// This function is installed by default to handle the case that the +/// interrupt dispatch code is entered in response to an external critical or +/// non-critical interrupt, but no interrupt is found pending in the interrupt +/// controller. This should never happen, as it would indicate that a +/// 'glitch' occurred on the external noncritical or critical interrupt input +/// to the PPC405 core. + +void __ppc405_phantom_irq_handler(void *arg, + SsxIrqId irq, + int critical) +{ + SSX_PANIC(PPC405_PHANTOM_INTERRUPT); +} + + +#undef __PPC405_IRQ_CORE_C__ diff --git a/src/ssx/ppc405/ppc405_irq_init.c b/src/ssx/ppc405/ppc405_irq_init.c new file mode 100755 index 0000000..da33947 --- /dev/null +++ b/src/ssx/ppc405/ppc405_irq_init.c @@ -0,0 +1,169 @@ +// $Id: ppc405_irq_init.c,v 1.2 2014/02/03 01:30:42 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_irq_init.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_irq_init.c +/// \brief PPC405 IRQ initialization routines +/// +/// The entry points in this file are routines that are typically used during +/// initialization, and their code space could be deallocated and recovered if +/// no longer needed by the application after initialization. + +#include "ssx.h" + +/// Set up a PPC405 Fixed Interval Timer (FIT) handler +/// +/// See the SSX specification for full details on setting up a FIT handler. +/// +/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_ARGUMENT_PPC405_FIT The \a tcr_fp argument was +/// invalid when called with a non-null (non-0) \a handler. + +// Since the SSX_CRITICAL Watchdog interrupt is also controlled by the TCR, we +// need to enter an SSX_CRITICAL critical section to manipulate the TCR. + +int +ppc405_fit_setup(int tcr_fp, SsxIrqHandler handler, void* arg) +{ + SsxMachineContext ctx; + Ppc405TCR tcr; + + if (SSX_ERROR_CHECK_API && handler) { + SSX_ERROR_IF((tcr_fp < 0) || + (tcr_fp > 3), + SSX_INVALID_ARGUMENT_PPC405_FIT); + } + + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + + tcr.value = mfspr(SPRN_TCR); + + if (handler) { + + tcr.fields.fp = tcr_fp; + tcr.fields.fie = 1; + + __ppc405_fit_routine = handler; + __ppc405_fit_arg = arg; + + } else { + + tcr.fields.fie = 0; + } + + mtspr(SPRN_TCR, tcr.value); + isync(); + + ssx_critical_section_exit(&ctx); + + return SSX_OK; +} + + +/// Set up a PPC405 Watchdog interrupt handler +/// +/// See the SSX specification for full details on setting up a watchdog +/// handler. +/// +/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_ARGUMENT_PPC405_WATCHDOG One or more of the \a tcr_wp +/// or \a tcr_wrc arguments were invalid. + +int +ppc405_watchdog_setup(int tcr_wp, int tcr_wrc, + SsxIrqHandler handler, void* arg) +{ + SsxMachineContext ctx; + Ppc405TCR tcr; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((tcr_wp < 0) || + (tcr_wp > 3) || + (tcr_wrc < 0) || + (tcr_wrc > 3), + SSX_INVALID_ARGUMENT_PPC405_WATCHDOG); + } + + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + + mtspr(SPRN_TSR, TSR_ENW | TSR_WIS); + + tcr.value = mfspr(SPRN_TCR); + + tcr.fields.wp = tcr_wp; + tcr.fields.wrc = tcr_wrc; + + if (handler == 0) { + + // Reinstall the default handler and clear the interrupt enable. Then + // clear any pending interrupt status. + // WIS. + + __ppc405_watchdog_routine = __ppc405_default_irq_handler; + __ppc405_watchdog_arg = 0; + + tcr.fields.wie = 0; + mtspr(SPRN_TCR, tcr.value); + isync(); + + mtspr(SPRN_TSR, TSR_WIS); + isync(); + + } else { + + // Install the new handler and enable the watchdog interrup. + + __ppc405_watchdog_routine = handler; + __ppc405_watchdog_arg = arg; + + tcr.fields.wie = 1; + mtspr(SPRN_TCR, tcr.value); + isync(); + } + + ssx_critical_section_exit(&ctx); + + return SSX_OK; +} + + +/// Set up a PPC405 Debug interrupt handler +/// +/// See the SSX specification for full details on setting up a debug handler. +/// +/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_ARGUMENT_PPC405_DEBUG The \a handler argument +/// is null (0). + +// The debug handler is installed in an SSX_CRITICAL critical section with all +// debug interrupts disabled as well. + +int +ppc405_debug_setup(SsxIrqHandler handler, void* arg) +{ + SsxMachineContext ctx; + + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + andc_msr(MSR_DE | MSR_DWE); + + __ppc405_debug_routine = handler; + __ppc405_debug_arg = arg; + isync(); + + ssx_critical_section_exit(&ctx); + + return SSX_OK; +} diff --git a/src/ssx/ppc405/ppc405_lib_core.c b/src/ssx/ppc405/ppc405_lib_core.c new file mode 100755 index 0000000..3086efb --- /dev/null +++ b/src/ssx/ppc405/ppc405_lib_core.c @@ -0,0 +1,42 @@ +// $Id: ppc405_lib_core.c,v 1.2 2014/06/26 13:00:11 cmolsen Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_lib_core.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_lib_core.c +/// \brief PPC405-specific library procedures +/// +/// The routines in this file are not part of SSX per se, but are included +/// with SSX because they may be considered OS services. +/// +/// These are core routines that will present in all PPC405 SSX applications. + +#include "ssx.h" + +/// Cause a PPC405 core reset by an action on DBCR0 + +void +ppc405_core_reset() +{ + or_spr(SPRN_DBCR0, DBCR0_RST_CORE); +} + +/// Cause a PPC405 chip reset by an action on DBCR0 + +void +ppc405_chip_reset() +{ + or_spr(SPRN_DBCR0, DBCR0_RST_CHIP); +} + +/// Cause a PPC405 system reset by an action on DBCR0 + +void +ppc405_system_reset() +{ + or_spr(SPRN_DBCR0, DBCR0_RST_SYSTEM); +} + diff --git a/src/ssx/ppc405/ppc405_mmu.c b/src/ssx/ppc405/ppc405_mmu.c new file mode 100755 index 0000000..1affc67 --- /dev/null +++ b/src/ssx/ppc405/ppc405_mmu.c @@ -0,0 +1,474 @@ +// $Id: ppc405_mmu.c,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_mmu.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_mmu.c +/// \brief Functions related to the PPC405 MMU and its use in SSX. +/// +/// SSX currently only supports using the PPC405 MMU for instruction and data +/// area translation and protection for the global SSX application and kernel. +/// No support for demand paging, user vs. kernel protection or +/// thread-specific protection is provided. +/// +/// Instead, the ppc405_mmu_map() API is provided. This API sets up TLB +/// entries that provide address translation and protection for a region of +/// memory. TLB entries are "locked", that is, once a TLB entry is defined it +/// is permanently defined. SSX makes use of the variable page sizes provided +/// by the PPC405 to protect regions using the minimum number of TLB entries. +/// The minimum page size is 1K, and all regions to be protected must be 1K +/// aligned and have sizes that are multiples of 1K. +/// +/// The ppc405_mmu_map() API optionally returns a Ppc405MmuMap descriptor. +/// This descriptor can be later used as the argument to ppc405_mmu_unmap() to +/// unmap the region. +/// +/// The overall SSX configuration option is PPC405_MMU_SUPPORT, with +/// suboptions PPC405_IR_SUPPORT and PPC405_DR_SUPPORT. The IR (instruction +/// relocate) and DR (data relocate) bits of the MSR must be set to enable +/// instruction and data translation/protection respectively. In SSX this is +/// handled by the definition of a macro PPC405_RELOCATION_MODE that contains +/// the IR and/or DR bits as configured. This macro is OR'ed with the default +/// PPC405 SSX_THREAD_MACHINE_CONTEXT_DEFAULT. If the application defines its +/// own SSX_THREAD_MACHINE_CONTEXT_DEFAULT then the application will have to +/// take care of ensuring that the correct IR/DR settings go into the default. +/// +/// During interrupts and context switches the relocation mode is +/// re-established before any loads or stores take place which provides +/// complete protection for interrupt handlers. Note the +/// assumption/requirement that all kernel, interrupt and thread code will be +/// run under the PPC405_RELOCATION_MODE. + +#include "ssx.h" +#include "ppc405_mmu.h" + +// A map of free TLB entries. +// +// It's handy that the PPC405 TLB has 64 entries. Thus we can use a 64-bit +// bit mask to represent free entries. The next free entry is quickly found +// using cntlz64(). +uint64_t __ppc405_tlb_free = 0; + +/// Reset the PPC405 simple MMU translation/protection scheme +/// +/// This API invalidates the TLB, clears the zone protection register, and +/// otherwise resets the SSX simple translation/protcetion scheme for the +/// PPC405. The application must not be running in a translated mode when +/// this API is invoked. +/// +/// \retval 0 Success +/// +/// \retval -PPC405_MMU_ILLEGAL_CONTEXT The API was called with translation +/// enabled. + +int +ppc405_mmu_reset() +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(mfmsr() & (MSR_IR | MSR_DR), + PPC405_MMU_ILLEGAL_CONTEXT); + } + + tlbia(); + mtspr(SPRN_PID, 0); + mtspr(SPRN_ZPR, 0); + __ppc405_tlb_free = 0xffffffffffffffffull; + isync(); + + return 0; +} + + +/// Define a memory region for MMU protection purposes +/// +/// \param effective_address The effective (virtual) base address of the +/// region. This address must be at least 1KB aligned. +/// +/// \param real_address The real base address of the region. This address +/// must be at least 1KB aligned. +/// +/// \param size The size of the region in bytes. The size must be a multiple +/// of 1KB. A \a size of 0 is legal and creates no entries. +/// +/// \param tlbhi_flags An OR combination of PPC405_TLBHI_* bits (excluding the +/// V-bit). This parameter is unlikely to be non-0 as it contains only the +/// little-endian (E) and U0 flags. +/// +/// - TLBHI_E : Little Endian +/// - TLBHI_U0 : U0 mode access +/// +/// \param tlblo_flags An OR combination of PPC405_TLBLO_* bits. This +/// parameter defines WR and EX protection, as well as the 'WIMG' bits. +/// +/// - TLBLO_EX : Executable code +/// - TLBLO_WR : Writable data +/// - TLBLO_W : Write-through mode +/// - TLBLO_I : Cache-inhibited +/// - TLBLO_M : Memory Coherent (Implemented but Ignored) +/// - TLBLO_G : Guarded +/// +/// \param map If non-0, then a Ppc405TlbMap for the region is returned. +/// This map can be later used as an argument to ppc405_mmu_unmap() to unmap +/// the region. +/// +/// This API creates fixed TLB entries that provide virtual-to-real address +/// translation and protection using a minimum number of TLB entries. The +/// number of TLB entries is fixed, so there is no guarantee in general that +/// any particular memory map is feasible. In general it is helpful to make +/// sure that the effective and real memory ranges have similar alignment, +/// otherwise the algorithm will be forced to use small page sizes. +/// +/// The caller is responsible for cache-correctness of this API. If necessary +/// the caller should flush or invalidate memory areas whose protection +/// attributes have changed prior to and/or after invoking this API. +/// +/// Note the the simple translation/protection protocol supported by this SSX +/// API does not support the "zone selection" field of the PPC405 TLB +/// entry. In SSX the PID is always 0. +/// +/// If SSX_ERROR_CHECK_API is configured, the API checks each new TLB entry to +/// ensure that it does not duplicate an existing entry. The check only +/// covers duplicated effective addresses (which are not supported by the +/// hardware), not the real addresses. +/// +/// \retval 0 Success +/// +/// \retval -PPC405_MMU_INVALID_ARGUMENT Can be signalled by numerous errors +/// including improperly aigned memory regions, region size not a multiple of +/// 1KB, and illegal flags. +/// +/// \retval -PPC405_TOO_MANY_TLB_ENTRIES There are not enough TLB entries left +/// to completely map the region. The state of the TLB at this point may be +/// inconsistent. +/// +/// \retval -PPC405_DUPLICATE_TLB_ENTRY The requested mapping would duplicate +/// all or part of a currently existing TLB entry. Duplicate entries are not +/// supported in the 405 core and will cause a TLB miss if an address in a +/// duplicated range is accessed. + +int +ppc405_mmu_map(SsxAddress effective_address, + SsxAddress real_address, + size_t size, int tlbhi_flags, int tlblo_flags, + Ppc405MmuMap *map) +{ + size_t log_page_size; + size_t page_size = 0; + Ppc405Tlbhi tlbhi; + Ppc405Tlblo tlblo; + Ppc405MmuMap local_map = 0; + int tlb_entry; + uint64_t bit; + SsxMachineContext ctx; + + if (SSX_ERROR_CHECK_API) { + uint64_t allocated; + SsxAddress this_effective_address; + int entry, overlap; + + // Check alignment, wrapping and legal flags. + + SSX_ERROR_IF((effective_address % PPC405_PAGE_SIZE_MIN) || + (real_address % PPC405_PAGE_SIZE_MIN) || + (size % PPC405_PAGE_SIZE_MIN) || + ((effective_address + size - 1) < effective_address) || + (tlbhi_flags & ~TLBHI_LEGAL_FLAGS) || + (tlblo_flags & ~TLBLO_LEGAL_FLAGS), + PPC405_MMU_INVALID_ARGUMENT); + + // The check for duplicate entries needs to be done iteratively since + // we don't use a fixed page size. Since this API will probably only + // be called during initialization or from thread contexts, and since + // the TLB size is small, this overhead is not considered too onerous. + // For complete correctness this check would need to be done in its + // entirity in an SSX_CRITICAL critical section. In order to reduce + // SSX_CRITICAL interrupt latency we simply check against the TLB + // entries that were allocated at the time of the API call. This code + // may not protect against multiple threads simultaneously creating + // mappings that duplicate each other (a super-bug), but it should + // protect against bugs in a single thread's updating of the TLB. + + if (size != 0) { + + // See if the requested effective address is already mapped in the + // TLB + + overlap = tlbsx(effective_address, &entry); + + // Iteratively check the other overlap condition, which is the + // case that the effective address of any TLB entry is in the + // range of the new request. + + allocated = ~__ppc405_tlb_free; + while (!overlap && (allocated != 0)) { + + entry = cntlz64(allocated); + allocated &= ~((uint64_t)1 << (63 - entry)); + + tlbhi.value = tlbrehi(entry); + if (tlbhi.fields.v) { + + this_effective_address = + tlbhi.fields.epn << PPC405_LOG_PAGE_SIZE_MIN; + + + // See if the first byte of this entry is inside the + // requested effective address range. NB: use actual + // address ranges (addr + size - 1) to compute overlap to + // avoid overflow. + + overlap |= + (this_effective_address >= + effective_address) && + (this_effective_address <= + (effective_address + size - 1)); + } + } + SSX_ERROR_IF(overlap, PPC405_DUPLICATE_TLB_ENTRY); + } + } + + // NB: PPC405 page sizes go from 1K to 16M by factors of 4. This is a + // 'greedy' algorithm that packs the region into the fewest number of + // pages, by using the largest possible (aligned) page size for the + // remaining memory area. + + while (size != 0) { + + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF_CRITICAL(__ppc405_tlb_free == 0, + PPC405_TOO_MANY_TLB_ENTRIES, + &ctx); + } + + tlb_entry = cntlz64(__ppc405_tlb_free); + bit = 0x8000000000000000ull >> tlb_entry; + __ppc405_tlb_free &= ~bit; + local_map |= bit; + + ssx_critical_section_exit(&ctx); + + log_page_size = PPC405_LOG_PAGE_SIZE_MAX; + do { + page_size = POW2_32(log_page_size); + if ((size >= page_size) && + ((effective_address & (page_size - 1)) == 0) && + ((real_address & (page_size - 1)) == 0)) { + break; + } else { + log_page_size -= 2; + } + } while (1); + + size -= page_size; + + // Create and install the TLB entries. The installation is done in a + // critical section to avoid any chance of another entity seeing an + // inconsistent TLB. + + tlbhi.value = tlbhi_flags; + tlbhi.fields.epn = effective_address >> PPC405_LOG_PAGE_SIZE_MIN; + tlbhi.fields.size = (log_page_size - PPC405_LOG_PAGE_SIZE_MIN) / 2; + tlbhi.fields.v = 1; + + tlblo.value = tlblo_flags; + tlblo.fields.rpn = real_address >> PPC405_LOG_PAGE_SIZE_MIN; + + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + + tlbwelo(tlb_entry, tlblo.value); + tlbwehi(tlb_entry, tlbhi.value); + isync(); + + ssx_critical_section_exit(&ctx); + + effective_address += page_size; + real_address += page_size; + } + + if (map) { + *map = local_map; + } + + return 0; +} + + +/// Un-define a memory region for MMU protection purposes +/// +/// \param map A pointer to a Ppc405MmuMap object created by ppc405_mmu_map() +/// when the memory region was mapped. This map is used to invalidate the TLB +/// entries associated with the map, then the map itself is invalidated. +/// +/// The caller is responsible for cache-correctness of this API. If necessary +/// the caller should flush or invalidate memory areas whose protection +/// attributes have changed prior to and/or after invoking this API. +/// +/// \retval 0 Success +/// +/// \retval -PPC405_MMU_INVALID_ARGUMENT The \a map pointer is null (0). + +int +ppc405_mmu_unmap(Ppc405MmuMap *map) +{ + int tlb_entry; + uint64_t bit; + SsxMachineContext ctx; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(map == 0, PPC405_MMU_INVALID_ARGUMENT); + } + + while ((tlb_entry = cntlz64(*map)) != 64) { + + bit = 0x8000000000000000ull >> tlb_entry; + *map &= ~bit; + tlbwehi(tlb_entry, 0); + isync(); + + ssx_critical_section_enter(SSX_CRITICAL, &ctx); + + __ppc405_tlb_free |= bit; + + ssx_critical_section_exit(&ctx); + } + + return 0; +} + + +/// Produce a dump of the TLB +/// +/// \param[in] i_stream The output stream for the dump +/// +/// \param[in] i_map An optional pointer. If NULL (0) then a full report is +/// printed. If non-null then only the entries recorded in the \a i_map are +/// printed. + +void +ppc405_mmu_report(FILE* i_stream, Ppc405MmuMap* i_map) +{ + size_t i; + Ppc405Tlbhi tlbhi; + Ppc405Tlblo tlblo; + uint32_t size, eff_lo, eff_hi, real_lo, real_hi; + const char *size_string[] = { + " 1K", " 4K", " 16K", " 64K", "256K", " 1M", " 4M", " 16M" + }; + Ppc405MmuMap map; + + fprintf(i_stream, "------------------------------------------------------------------------------\n"); + if (i_map == 0) { + fprintf(i_stream, "-- PPC405 MMU : Full Report --\n"); + } else { + fprintf(i_stream, "-- PPC405 MMU : Partial Report --\n"); + } + fprintf(i_stream, "------------------------------------------------------------------------------\n"); + fprintf(i_stream, "-- # Effective Real Size EX/WR WIMG Other --\n"); + fprintf(i_stream, "------------------------------------------------------------------------------\n"); + + if (i_map == 0) { + map = __ppc405_tlb_free; + } else { + map = ~*i_map; + } + + for (i = 0; i < PPC405_TLB_ENTRIES; i++, map <<= 1) { + + if (map & 0x8000000000000000ull) { + continue; + } + + tlbhi.value = tlbrehi(i); + tlblo.value = tlbrelo(i); + + if (tlbhi.fields.v) { + + size = + POW2_32(PPC405_LOG_PAGE_SIZE_MIN) << (2 * tlbhi.fields.size); + + eff_lo = tlbhi.fields.epn << PPC405_LOG_PAGE_SIZE_MIN; + eff_hi = eff_lo + size - 1; + + real_lo = tlblo.fields.rpn << PPC405_LOG_PAGE_SIZE_MIN; + real_hi = real_lo + size - 1; + + fprintf(i_stream, "-- %2d : %08x:%08x -> %08x:%08x : %s : %s %s : %s%s%s%s : %s%s --\n", + i, + eff_lo, eff_hi, + real_lo, real_hi, + size_string[tlbhi.fields.size], + tlblo.fields.ex ? "EX" : " ", + tlblo.fields.wr ? "WR" : " ", + tlblo.fields.w ? "W" : " ", + tlblo.fields.i ? "I" : " ", + tlblo.fields.m ? "M" : " ", + tlblo.fields.g ? "G" : " ", + tlbhi.fields.e ? "E" : " ", + tlbhi.fields.u0 ? "U0" : " "); + } else { + fprintf(i_stream, "-- %2d : ENTRY NOT VALID\n", i); + } + } + + fprintf(i_stream, "------------------------------------------------------------------------------\n"); +} + + +/// Perform a memcpy() without address translation (protection) +/// +/// It sometimes arises that "read-only" data needs to be initialized at +/// run-time. This can be accomplished in general by temporarily disabling +/// translation (protection) while the "read-only" data is altered. Another +/// option is to use the memcpy_real() API to copy an image of the data from +/// writable memory to memory marked read-only by the MMU. +/// +/// The memcpy_real() function copies \a n bytes from memory area \a src to +/// memory area \a dest, with translation disabled. The memory areas should +/// not overlap. The memcpy_real() function returns a pointer to dest. +/// +/// This is a general-purpose API that makes no assumption about the +/// cacheability of the data, and can also be used to move code from data +/// areas to text areas as the I-cache is always invalidated after the copy. +/// The algorithm is as follows: +/// +/// - Flush the \a dest data from the D-cache +/// - Disable translation +/// - memcpy() the \a src to the \a dest +/// - Flush the \a dest data from the D-cache +/// - Invalidate the I-cache +/// - Re-enable translation (if it had been previously enabled) +/// +/// \note Any synchronization access required for \a dest or \a src is the +/// responsibility of the caller. +void* +memcpy_real(void* dest, const void* src, size_t n) +{ + uint32_t msr; + + dcache_flush(dest, n); + + msr = mfmsr(); + mtmsr(msr & ~(MSR_IR | MSR_DR)); + sync(); /* HW239446! */ + + memcpy(dest, src, n); + + dcache_flush(dest, n); + + icache_invalidate_all(); + + mtmsr(msr); + sync(); /* HW239446! */ + + return dest; +} + + + + diff --git a/src/ssx/ppc405/ppc405_mmu.h b/src/ssx/ppc405/ppc405_mmu.h new file mode 100755 index 0000000..cd7e249 --- /dev/null +++ b/src/ssx/ppc405/ppc405_mmu.h @@ -0,0 +1,170 @@ +#ifndef __PPC405_MMU_H__ +#define __PPC405_MMU_H__ + +// $Id: ppc405_mmu.h,v 1.1.1.1 2013/12/11 21:03:26 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_mmu.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_mmu.h +/// \brief Definitions related to the PPC405 MMU and its use in SSX. + +#ifndef __ASSEMBLER__ + +#include "ssx_io.h" +#include <stdint.h> + +/// The PPC405 TLBHI (tag) structure +/// +/// Note that in hardware this is a 36-bit register, as it includes the TID +/// field. When writing, TID is set from the current PID, and when reading PID +/// is set from the TID entry of the register. + +typedef union { + uint32_t value; + struct { + uint32_t epn : 22; + uint32_t size : 3; + uint32_t v : 1; + uint32_t e : 1; + uint32_t u0 : 1; + } fields; +} Ppc405Tlbhi; + + +/// The PPC405 TLBLO (Data) structure + +typedef union { + uint32_t value; + struct { + uint32_t rpn : 22; + uint32_t ex : 1; + uint32_t wr : 1; + uint32_t zsel : 4; + uint32_t w : 1; + uint32_t i : 1; + uint32_t m : 1; + uint32_t g : 1; + } fields; +} Ppc405Tlblo; + +#endif /* __ASSEMBLER__ */ + +// TLBHI contains little-endian and U0 flags (probably never used) + +#define TLBHI_E 0x00000020 +#define TLBHI_U0 0x00000010 + +#define TLBHI_LEGAL_FLAGS (TLBHI_E | TLBHI_U0) + +// TLBLO contains WIMG + EX/WR bits + +#define TLBLO_EX 0x00000200 +#define TLBLO_WR 0x00000100 +#define TLBLO_W 0x00000008 +#define TLBLO_I 0x00000004 +#define TLBLO_M 0x00000002 +#define TLBLO_G 0x00000001 + +#define TLBLO_LEGAL_FLAGS \ + (TLBLO_EX | TLBLO_WR | TLBLO_W | TLBLO_I | TLBLO_M | TLBLO_G) + + +#define PPC405_TLB_ENTRIES 64 + +#define PPC405_PAGE_SIZE_MIN 1024 +#define PPC405_PAGE_SIZE_MAX (16 * 1024 * 1024) + +#define PPC405_LOG_PAGE_SIZE_MIN 10 +#define PPC405_LOG_PAGE_SIZE_MAX 24 + +#define PPC405_PAGE_SIZE_1K 0 +#define PPC405_PAGE_SIZE_4K 1 +#define PPC405_PAGE_SIZE_16K 2 +#define PPC405_PAGE_SIZE_64K 3 +#define PPC405_PAGE_SIZE_256K 4 +#define PPC405_PAGE_SIZE_1M 5 +#define PPC405_PAGE_SIZE_4M 6 +#define PPC405_PAGE_SIZE_16M 7 + +// PPC405 MMU error and panic codes + +#define PPC405_MMU_ILLEGAL_CONTEXT 0x00668001 +#define PPC405_MMU_INVALID_ARGUMENT 0x00668002 +#define PPC405_TOO_MANY_TLB_ENTRIES 0x00668003 +#define PPC405_DUPLICATE_TLB_ENTRY 0x00668004 + + +#ifndef __ASSEMBLER__ + +/// A descriptor of a memory region statically defined in the TLB +/// +/// These maps are returned by ppc405_mmu_map(), and can be used later +/// to unmap the region with ppc405_mmu_unmap(). They can also be used to +/// control what gets printed by ppc405_mmu_report(). +typedef uint64_t Ppc405MmuMap; + +/// TLBIA +#define tlbia() asm volatile ("tlbia" : : : "memory") + +/// TLBWEHI +#define tlbwehi(entry, tlbhi) \ +asm volatile ("tlbwehi %0, %1" : : "r" (tlbhi), "r" (entry) : "memory") + +/// TLBWELO +#define tlbwelo(entry, tlblo) \ +asm volatile ("tlbwelo %0, %1" : : "r" (tlblo), "r" (entry) : "memory") + +/// TLBREHI +#define tlbrehi(entry) \ + ({ \ + uint32_t __tlbhi; \ + asm volatile ("tlbrehi %0, %1" : "=r" (__tlbhi) : "r" (entry)); \ + __tlbhi;}) + +/// TLBRELO +#define tlbrelo(entry) \ + ({ \ + uint32_t __tlblo; \ + asm volatile ("tlbrelo %0, %1" : "=r" (__tlblo) : "r" (entry)); \ + __tlblo;}) + +/// TLBSX +/// +/// Returns 1 if the address is mapped, else 0. If positive the integer +/// pointed to by \a entry is updated with the TLB index of the matching +/// entry, otherwise the return value is undefined. +#define tlbsx(address, entry) \ + ({ \ + uint32_t __cr, __entry; \ + asm volatile ("tlbsx. %0, 0, %2; mfcr %1" : \ + "=r" (__entry), "=r" (__cr) : "r" (address)); \ + *(entry) = __entry; \ + ((__cr & CR_EQ(0)) != 0);}) + + +int +ppc405_mmu_reset(void); + +int +ppc405_mmu_map(SsxAddress effective_address, + SsxAddress real_address, + size_t size, int tlbhi_flags, int tlblo_flags, + Ppc405MmuMap *map); + +int +ppc405_mmu_unmap(Ppc405MmuMap *map); + +void +ppc405_mmu_start(void); + +void +ppc405_mmu_report(FILE* stream, Ppc405MmuMap* map); + +#endif /* __ASSEMBLER__ */ + + +#endif /* __PPC405_MMU_H__ */ diff --git a/src/ssx/ppc405/ppc405_mmu_asm.S b/src/ssx/ppc405/ppc405_mmu_asm.S new file mode 100755 index 0000000..1118779 --- /dev/null +++ b/src/ssx/ppc405/ppc405_mmu_asm.S @@ -0,0 +1,73 @@ +// $Id: ppc405_mmu_asm.S,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_mmu_asm.S,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_mmu_asm.S +/// \brief Assembler support for PPC405 MMU operations +/// +/// Currently the only API in this file - ppc405_mmu_start() - is likely an +/// initialization-only API that could be removed from the run-time image. + + .nolist +#include "ssx.h" + .list + +/// Start MMU mode on the PPC405 +/// +/// This API enables PPC405 address translation of the type supported by SSX - +/// simple 1 to 1 effective - real translation for the purpose of +/// protection. It is coded in assembler to ensure that this transition is +/// done as cache-safely as generically possible. The API enters a critical +/// section and flushes the data cache and invalidates the I-cache, then +/// enables the translation modes specifed by PPC405_RELOCATION_MODE. +/// Following is a final invalidation of the I-cache. +/// +/// \cond + + .global_function ppc405_mmu_start +ppc405_mmu_start: + + ## Create and link a stack frame + + stwu %r1, -16(%r1) + mflr %r0 + stw %r0, 20(%r1) + + ## Enter critical section, save original MSR in R31 + + stw %r31, 8(%r1) + _ssx_critical_section_enter SSX_CRITICAL, %r31, %r4 + + ## Flush D-cache, Invalidate I-Cache + + bl dcache_flush_all + bl icache_invalidate_all + + ## Enter translation mode on original MSR (removing critical section) + + _liw %r3, 1f + mtsrr0 %r3 + _liwa %r3, PPC405_RELOCATION_MODE + or %r3, %r31, %r3 + mtsrr1 %r3 + rfi +1: + ## Invalidate I-cache again + + bl icache_invalidate_all + + ## Restore R31, Unwind stack and return + + lwz %r31, 8(%r1) + lwz %r0, 20(%r1) + mtlr %r0 + addi %r1, %r1, 16 + blr + + .epilogue ppc405_mmu_start + +/// \endcond diff --git a/src/ssx/ppc405/ppc405_msr.h b/src/ssx/ppc405/ppc405_msr.h new file mode 100755 index 0000000..645a052 --- /dev/null +++ b/src/ssx/ppc405/ppc405_msr.h @@ -0,0 +1,85 @@ +#ifndef __PPC405_MSR_H__ +#define __PPC405_MSR_H__ + +// $Id: ppc405_msr.h,v 1.1.1.1 2013/12/11 21:03:26 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_msr.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_msr.h +/// \brief Everything related to the PPC405 Machine State Register +/// +/// All of the macros defined here that \e modify the MSR create a compiler +/// memory barrier that will cause GCC to flush/invalidate all memory data +/// held in registers before the macro. This is consistent with other systems, +/// e.g., the PowerPC Linux kernel, and is the safest way to define these +/// macros as it guarantess for example that kernel data structure updates +/// have completed before exiting a critical section. + +#define MSR_AP 0x02000000 /* APU Available */ +#define MSR_APE 0x00080000 /* APU Exception Enable */ +#define MSR_WE 0x00040000 /* Wait State Enable */ +#define MSR_CE 0x00020000 /* Critical Interrupt Enable */ +#define MSR_EE 0x00008000 /* External Interrupt Enable */ +#define MSR_PR 0x00004000 /* Problem State */ +#define MSR_ME 0x00001000 /* Machine Check Exception Enable */ +#define MSR_FE0 0x00000800 /* Floating-Point Exception Mode 0 */ +#define MSR_DWE 0x00000400 /* Debug Wait Enable */ +#define MSR_DE 0x00000200 /* Debug Interrupt Enable */ +#define MSR_IR 0x00000020 /* Instruction Relocation */ +#define MSR_DR 0x00000010 /* Data Relocation */ + +#define MSR_CE_BIT 14 +#define MSR_EE_BIT 16 +#define MSR_IR_BIT 26 +#define MSR_DR_BIT 27 + +#ifndef __ASSEMBLER__ + +/// Move From MSR + +#define mfmsr() \ + ({uint32_t __msr; \ + asm volatile ("mfmsr %0" : "=r" (__msr)); \ + __msr;}) + + +/// Move to MSR + +#define mtmsr(value) \ + asm volatile ("mtmsr %0; isync" : : "r" (value) : "memory") + + +/// Read-Modify-Write the MSR with OR (Set MSR bits). This operation is only +/// guaranteed atomic in a critical section. + +#define or_msr(x) \ + mtmsr(mfmsr() | (x)) + + +/// Read-Modify-Write the MSR with AND complement (Clear MSR bits). This +/// operation is only guaranteed atomic in a critical section. + +#define andc_msr(x) \ + mtmsr(mfmsr() & ~(x)) + + +/// Write MSR[EE] with an immediate value (0/1) +/// +/// Note that the immediate value \a i must be a compile-time constant. + +#define wrteei(i) \ + asm volatile ("wrteei %0; isync" : : "i" (i) : "memory") + + +/// Write MSR[EE] from the EE bit of another MSR + +#define wrtee(other_msr) \ + asm volatile ("wrtee %0; isync" : : "r" (other_msr) : "memory") + +#endif /* __ASSEMBLER__ */ + +#endif /* __PPC405_MSR_H__ */ diff --git a/src/ssx/ppc405/ppc405_spr.h b/src/ssx/ppc405/ppc405_spr.h new file mode 100755 index 0000000..ede91cb --- /dev/null +++ b/src/ssx/ppc405/ppc405_spr.h @@ -0,0 +1,319 @@ +#ifndef __PPC405_SPR_H__ +#define __PPC405_SPR_H__ + +// $Id: ppc405_spr.h,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_spr.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_spr.h +/// \brief Everything related to PPC405-specific SPRs + +/// \defgroup ppc405_sprs PowerPC 405 SPRs +/// +/// These are the documented SPRs of the PPC405. Most of these SPRs are +/// available in RISCWatch and eCmd using the defined names (minus SPRN_). In +/// some cases RISCWatch/eCMD use different names, which appear in square +/// brackets in the brief comments for each register. RISCWatch/eCMD also +/// allow CR, MSR and IAR (Instruction Address Register) to be accessed as +/// SPRs. +/// +/// @{ + +#define SPRN_CCR0 0x3b3 /// Core configuration register 0 +#define SPRN_CCR1 0x378 /// Core configuration register 1 +#define SPRN_CTR 0x009 /// Count register +#define SPRN_DAC1 0x3f6 /// Data address compare 1 +#define SPRN_DAC2 0x3f7 /// Data address compare 2 +#define SPRN_DBCR0 0x3f2 /// Debug control register 0 +#define SPRN_DBCR1 0x3bd /// Debug control register 1 +#define SPRN_DBSR 0x3f0 /// Debug status register +#define SPRN_DCCR 0x3fa /// Data cacheability (real mode) +#define SPRN_DCWR 0x3ba /// Data cache writeback (real mode) +#define SPRN_DEAR 0x3d5 /// Data exception address register +#define SPRN_DVC1 0x3b6 /// Data value compare 1 +#define SPRN_DVC2 0x3b7 /// Data value compare 2 +#define SPRN_ESR 0x3d4 /// Exception syndrome register +#define SPRN_EVPR 0x3d6 /// Exception. vec. prefix reg. +#define SPRN_IAC1 0x3f4 /// Instruction address compare 1 +#define SPRN_IAC2 0x3f5 /// Instruction address compare 2 +#define SPRN_IAC3 0x3b4 /// Instruction address compare 3 +#define SPRN_IAC4 0x3b5 /// Instruction address compare 4 +#define SPRN_ICCR 0x3fb /// Instruction cache. (real mode) +#define SPRN_ICDBDR 0x3d3 /// Instruction cache debug data reg. +#define SPRN_LR 0x008 /// Link register +#define SPRN_MCSR 0x23c /// Machine check syndrome register +#define SPRN_PID 0x3b1 /// Process ID +#define SPRN_PIT 0x3db /// Programmable interrupt timer +#define SPRN_PVR 0x11f /// Processor version register +#define SPRN_SGR 0x3b9 /// Storage guarded (real mode) +#define SPRN_SLER 0x3bb /// Storage little-endian (real mode) +#define SPRN_SPRG0 0x110 /// SPR general register 0 +#define SPRN_SPRG1 0x111 /// SPR general register 1 +#define SPRN_SPRG2 0x112 /// SPR general register 2 +#define SPRN_SPRG3 0x113 /// SPR general register 3 +#define SPRN_SPRG4 0x114 /// SPR general register 4 [SPRG4_W] +#define SPRN_SPRG5 0x115 /// SPR general register 5 [SPRG5_W] +#define SPRN_SPRG6 0x116 /// SPR general register 6 [SPRG6_W] +#define SPRN_SPRG7 0x117 /// SPR general register 7 [SPRG7_W] +#define SPRN_SRR0 0x01a /// Save/restore register 0 +#define SPRN_SRR1 0x01b /// Save/restore register 1 +#define SPRN_SRR2 0x3de /// Save/restore register 2 +#define SPRN_SRR3 0x3df /// Save/restore register 3 +#define SPRN_SU0R 0x3bc /// Storage user 0 (real mode) +#define SPRN_TBL 0x11c /// Time base lower [TBL_W] +#define SPRN_TBU 0x11d /// Time base upper [TBU_W] +#define SPRN_TCR 0x3da /// Timer control register +#define SPRN_TSR 0x3d8 /// Timer status register +#define SPRN_USPRG0 0x100 /// User read/write SPR general 0 +#define SPRN_XER 0x001 /// Fixed-point exception register +#define SPRN_ZPR 0x3b0 /// Zone protection register +#define SPRN_UR_SPRG4 0x104 /// User-readable SPRG4 [SPRG4_R] +#define SPRN_UR_SPRG5 0x105 /// User-readable SPRG5 [SPRG5_R] +#define SPRN_UR_SPRG6 0x106 /// User-readable SPRG6 [SPRG6_R] +#define SPRN_UR_SPRG7 0x107 /// User-readable SPRG7 [SPRG7_R] +#define SPRN_UR_TBL 0x10c /// User-readable TBL [TBL, TBL_R] +#define SPRN_UR_TBU 0x10d /// User-readable TBU [TBU, TBU_R] + +/// @} + +/// \defgroup ppc405_undocumented_sprs PowerPC 405 Undocumented SPRs +/// +/// These are undocumented SPRs related to RISCWatch and debugging. These +/// registers are also available in RISCWatch/eCMD. +/// +/// - DBDR is a scratch register used by RISCwatch when "RAM-ing" data in/out of +/// the core. This register can be read and written. +/// +/// - DBSRS and TSRS are "hidden" registers connected to DBSR and TSR +/// respectively. These are write-only registers. When written, any 1 bits in +/// the write data are OR-ed into the DBSR and TSR respectively, as a way to +/// force status bits and cause interrupts. +/// +/// @{ + +#define SPRN_DBDR 0x3f3 /// Debug data register 0x3f3 */ +#define SPRN_DBSRS 0x3f1 /// Debug status register set 0x3f1 */ +#define SPRN_TSRS 0x3d9 /// Timer status register set 0x3d9 */ + +/// @} + +/* CCR0 - Cache Control Register 0 */ + +#define CCR0_LWL 0x02000000 /* Load Word as Line */ +#define CCR0_LWOA 0x01000000 /* Load Without Allocate */ +#define CCR0_SWOA 0x00800000 /* Store Without Allocate */ +#define CCR0_DPP1 0x00400000 /* DCU PLB Priority Bit 1 */ +#define CCR0_IPP0 0x00200000 /* ICU PLB Priority Bit 0 */ +#define CCR0_IPP1 0x00100000 /* ICU PLB Priority Bit 1 */ +#define CCR0_DPE 0x00080000 /* Data Cache Parity Enable */ +#define CCR0_DPP 0x00040000 /* DCU Parity is Precise (0/1) */ +#define CCR0_U0XE 0x00020000 /* Enable U0 Exception */ +#define CCR0_LDBE 0x00010000 /* Load Debug Enable */ +#define CCR0_IPE 0x00002000 /* Instruction Cache Parity Enable */ +#define CCR0_TPE 0x00001000 /* TLB Parity Enable */ +#define CCR0_PFC 0x00000800 /* ICU Prefetching for Cacheable Regions */ +#define CCR0_PFNC 0x00000400 /* ICU Prefetching for Non-Cacheable Regions */ +#define CCR0_NCRS 0x00000200 /* Non-Cacheable ICU request is 16(0)/32(1)B */ +#define CCR0_FWOA 0x00000100 /* Fetch Without Allocate */ +#define CCR0_CIS 0x00000010 /* Cache Information Select Data(0)/Tag(1) */ +#define CCR0_PRS 0x00000008 /* Parity Read Select */ +#define CCR0_CWS 0x00000001 /* Cache Way Select A(0)/B(1) */ + +/* CCR1 - Cache Control Register 1 */ + +#define CCR1_ICTE 0x80000000 /* Instruction Cache Tag Parity Insertion */ +#define CCR1_ICDE 0x40000000 /* Instruction Cache Data Parity Insertion */ +#define CCR1_DCTE 0x20000000 /* Data Cache Tag Parity Insertion */ +#define CCR1_DCDE 0x10000000 /* Data Cache Data Parity Insertion */ +#define CCR1_TLBE 0x08000000 /* TLB Parity Insertion */ + +/* DBCR0 - Debug Control Register 0 */ + +#define DBCR0_EDM 0x80000000 /* External Debug Mode */ +#define DBCR0_IDM 0x40000000 /* Internal Debug Mode */ +#define DBCR0_RST_MASK 0x30000000 /* ReSeT */ +#define DBCR0_RST_NONE 0x00000000 /* No action */ +#define DBCR0_RST_CORE 0x10000000 /* Core reset */ +#define DBCR0_RST_CHIP 0x20000000 /* Chip reset */ +#define DBCR0_RST_SYSTEM 0x30000000 /* System reset */ +#define DBCR0_IC 0x08000000 /* Instruction Completion debug event */ +#define DBCR0_BT 0x04000000 /* Branch Taken debug event */ +#define DBCR0_EDE 0x02000000 /* Exception Debug Event */ +#define DBCR0_TDE 0x01000000 /* Trap Debug Event */ +#define DBCR0_IA1 0x00800000 /* IAC (Instruction Address Compare) 1 debug event */ +#define DBCR0_IA2 0x00400000 /* IAC 2 debug event */ +#define DBCR0_IA12 0x00200000 /* Instruction Address Range Compare 1-2 */ +#define DBCR0_IA12X 0x00100000 /* IA12 eXclusive */ +#define DBCR0_IA3 0x00080000 /* IAC 3 debug event */ +#define DBCR0_IA4 0x00040000 /* IAC 4 debug event */ +#define DBCR0_IA34 0x00020000 /* Instruction Address Range Compare 3-4 */ +#define DBCR0_IA34X 0x00010000 /* IA34 eXclusive */ +#define DBCR0_IA12T 0x00008000 /* Instruction Address Range Compare 1-2 range Toggle */ +#define DBCR0_IA34T 0x00004000 /* Instruction Address Range Compare 3-4 range Toggle */ +#define DBCR0_FT 0x00000001 /* Freeze Timers on debug event */ + +/* DBSR - Debug Status Register */ + +#define DBSR_IC 0x80000000 /* Instruction completion debug event */ +#define DBSR_BT 0x40000000 /* Branch Taken debug event */ +#define DBSR_EDE 0x20000000 /* Exception debug event */ +#define DBSR_TIE 0x10000000 /* Trap Instruction debug event */ +#define DBSR_UDE 0x08000000 /* Unconditional debug event */ +#define DBSR_IA1 0x04000000 /* IAC1 debug event */ +#define DBSR_IA2 0x02000000 /* IAC2 debug event */ +#define DBSR_DR1 0x01000000 /* DAC1 Read debug event */ +#define DBSR_DW1 0x00800000 /* DAC1 Write debug event */ +#define DBSR_DR2 0x00400000 /* DAC2 Read debug event */ +#define DBSR_DW2 0x00200000 /* DAC2 Write debug event */ +#define DBSR_IDE 0x00100000 /* Imprecise debug event */ +#define DBSR_IA3 0x00080000 /* IAC3 debug event */ +#define DBSR_IA4 0x00040000 /* IAC4 debug event */ +#define DBSR_MRR 0x00000300 /* Most recent reset */ + +/* TCR - Timer Control Register */ + +#define TCR_WP_MASK 0xc0000000 /* Watchdog Period mask */ +#define TCR_WP_2_17 0x00000000 /* 2**17 clocks */ +#define TCR_WP_2_21 0x40000000 /* 2**21 clocks */ +#define TCR_WP_2_25 0x80000000 /* 2**25 clocks */ +#define TCR_WP_2_29 0xc0000000 /* 2**29 clocks */ +#define TCR_WRC_MASK 0x30000000 /* Watchdog Reset Control mask */ +#define TCR_WRC_NONE 0x00000000 /* No watchdog reset */ +#define TCR_WRC_CORE 0x10000000 /* Core reset */ +#define TCR_WRC_CHIP 0x20000000 /* Chip reset */ +#define TCR_WRC_SYSTEM 0x30000000 /* System reset */ +#define TCR_WIE 0x08000000 /* Watchdog Interrupt Enable */ +#define TCR_PIE 0x04000000 /* PIT Interrupt Enable */ +#define TCR_FP_MASK 0x03000000 /* FIT Period */ +#define TCR_FP_2_9 0x00000000 /* 2**9 clocks */ +#define TCR_FP_2_13 0x01000000 /* 2**13 clocks */ +#define TCR_FP_2_17 0x02000000 /* 2**17 clocks */ +#define TCR_FP_2_21 0x03000000 /* 2**21 clocks */ +#define TCR_FIE 0x00800000 /* FIT Interrupt Enable */ +#define TCR_ARE 0x00400000 /* Auto-reload Enable */ + +#ifndef __ASSEMBLER__ + +typedef union { + uint32_t value; + struct { + unsigned int wp : 2; + unsigned int wrc : 2; + unsigned int wie : 1; + unsigned int pie : 1; + unsigned int fp : 2; + unsigned int fie : 1; + unsigned int are : 1; + unsigned int reserved : 22; + } fields; +} Ppc405TCR; + +#endif /* __ASSEMBLER__ */ + +/* TSR - Timer Status Register */ + +#define TSR_ENW 0x80000000 /* Enable Next Watchdog */ +#define TSR_WIS 0x40000000 /* Watchdog Interrupt Status */ +#define TSR_WRS_MASK 0x30000000 /* Watchdog Reset Status */ +#define TSR_WRS_NONE 0x00000000 /* No watchdog reset has occurred */ +#define TSR_WRS_CORE 0x10000000 /* Core reset was forced by the watchdog */ +#define TSR_WRS_CHIP 0x20000000 /* Chip reset was forced by the watchdog */ +#define TSR_WRS_SYSTEM 0x30000000 /* System reset was forced by the watchdog */ +#define TSR_PIS 0x08000000 /* PIT Interrupt Status */ +#define TSR_FIS 0x04000000 /* FIT Interrupt Status */ + +#ifndef __ASSEMBLER__ + +/// Move From SPR +/// +/// Note that \a sprn must be a compile-time constant. + +#define mfspr(sprn) \ + ({uint32_t __value; \ + asm volatile ("mfspr %0, %1" : "=r" (__value) : "i" (sprn)); \ + __value;}) + + +/// Move to SPR +/// +/// Note that \a sprn must be a compile-time constant. + +#define mtspr(sprn, value) \ + ({uint32_t __value = (value); \ + asm volatile ("mtspr %0, %1" : : "i" (sprn), "r" (__value)); \ + }) + + +/// Read-Modify-Write an SPR with OR (Set SPR bits) +/// +/// Note that \a sprn must be a compile-time constant. This operation is only +/// guaranteed atomic in a critical section. + +#define or_spr(sprn, x) \ + mtspr(sprn, mfspr(sprn) | (x)) + + +/// Read-Modify-Write an SPR with AND complement (Clear SPR bits) +/// +/// Note that \a sprn must be a compile-time constant. This operation is only +/// guaranteed atomic in a critical section. + +#define andc_spr(sprn, x) \ + mtspr(sprn, mfspr(sprn) & ~(x)) + + +/// Move From Time Base (Lower) + +#define mftb() mfspr(SPRN_TBL) + +/// Move To Time Base (Lower) + +#define mttbl(x) mtspr(SPRN_TBL, (x)) + +/// Move From Time Base (Upper) + +#define mftbu() mfspr(SPRN_TBU) + +/// Move To Time Base (UPPER) + +#define mttbu(x) mtspr(SPRN_TBU, (x)) + +#endif /* __ASSEMBLER__ */ + +#ifdef __ASSEMBLER__ + + /// \cond + + // Use this macro to define new mt<spr> and mf<spr> instructions that + // may not exist in the assembler. + + .macro _sprinstrs, name, num + .macro mt\name, reg + mtspr \num, \reg + .endm + .macro mf\name, reg + mfspr \reg, \num + .endm + .endm + + _sprinstrs ccr0, SPRN_CCR0 + _sprinstrs ccr1, SPRN_CCR1 + _sprinstrs dbcr0, SPRN_DBCR0 + _sprinstrs dbcr1, SPRN_DBCR1 + _sprinstrs dcwr, SPRN_DCWR + _sprinstrs mcsr, SPRN_MCSR + _sprinstrs pid, SPRN_PID + _sprinstrs sgr, SPRN_SGR + _sprinstrs sler, SPRN_SLER + _sprinstrs su0r, SPRN_SU0R + _sprinstrs usprg0, SPRN_USPRG0 + + /// \endcond + +#endif /* __ASSEMBLER__ */ + +#endif /* __PPC405_SPR_H__ */ diff --git a/src/ssx/ppc405/ppc405_thread_init.S b/src/ssx/ppc405/ppc405_thread_init.S new file mode 100755 index 0000000..47f5813 --- /dev/null +++ b/src/ssx/ppc405/ppc405_thread_init.S @@ -0,0 +1,126 @@ +// $Id: ppc405_thread_init.S,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ + +/// \file ppc405_thread_init.S +/// \brief PPC405-specific thread initialization +/// +/// The entry points in this file are routines that are typically used during +/// initialization, and their code space could be deallocated and recovered if +/// no longer needed by the application after initialization. + + .nolist +#include "ssx.h" + .list + +/// \fn void __ssx_thread_context_initialize(SsxThread *thread, SsxThreadRoutine thread_routine, void *private) +/// \brief Create the initial thread context on the stack +/// +/// The non-reserved GPRs are prepatterned with 0x0000\<rn\>\<rn\> where \<rn\> is +/// the register number (as decimal). The initial context is set up with the +/// thread running in the default machine context, and when the thread is +/// switched in it will begin executing at the entry point of the thread +/// routine with the \c private parameter in R3. The LR is initialized such +/// that when the thread returns, it will return to the entry point of \c +/// ssx_complete(). +#ifdef DOXYGEN_ONLY +void +__ssx_thread_context_initialize(SsxThread *thread, + SsxThreadRoutine thread_routine, + void *private); +#endif// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_thread_init.S,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \cond + + .global_function __ssx_thread_context_initialize + +__ssx_thread_context_initialize: + + ## R3 = thread (param) + ## R4 = thread_routine (param) + ## R5 = private (param) + ## R6 = thread stack pointer (computed) + ## R7 = scratch + + .macro _gpr_init, prefix, reg, val + li %r7, \val + stw %r7, \prefix\reg(%r6) + .endm + + ## Initialize a fast context on the thread stack. The CR is cleared, + ## the LR = ssx_complete(), R3 has the private parameter. + + lwz %r6, SSX_THREAD_OFFSET_SAVED_STACK_POINTER(%r3) + + stwu %r6, -SSX_FAST_CTX_SIZE(%r6) + + li %r7, 0 + stw %r7, SSX_FAST_CTX_CR(%r6) + + _liw %r7, ssx_complete + stw %r7, SSX_FAST_CTX_LR(%r6) + + stw %r5, SSX_FAST_CTX_GPR3(%r6) + + _gpr_init SSX_FAST_CTX_GPR, 4, 0x0404 + _gpr_init SSX_FAST_CTX_GPR, 5, 0x0505 + _gpr_init SSX_FAST_CTX_GPR, 6, 0x0606 + _gpr_init SSX_FAST_CTX_GPR, 7, 0x0707 + + ## Initialize the (volatile - fast) context on the thread stack. XER + ## and CTR are clear, SRR0 = thread_routine, SRR1 = default machine + ## context. + + stwu %r6, -SSX_VOL_FAST_CTX_SIZE(%r6) + + li %r7, 0 + stw %r7, SSX_VOL_FAST_CTX_XER(%r6) + stw %r7, SSX_VOL_FAST_CTX_CTR(%r6) + + stw %r4, SSX_VOL_FAST_CTX_SRR0(%r6) + + _lwzsd %r7, __ssx_thread_machine_context_default + stw %r7, SSX_VOL_FAST_CTX_SRR1(%r6) + + _gpr_init SSX_VOL_FAST_CTX_GPR, 0, 0x0000 + _gpr_init SSX_VOL_FAST_CTX_GPR, 8, 0x0808 + _gpr_init SSX_VOL_FAST_CTX_GPR, 9, 0x0909 + _gpr_init SSX_VOL_FAST_CTX_GPR, 10, 0x1010 + _gpr_init SSX_VOL_FAST_CTX_GPR, 11 0x1111 + _gpr_init SSX_VOL_FAST_CTX_GPR, 12 0x1212 + + ## Initialize the non-volatile context on the thread stack. + + stwu %r6, -SSX_NON_VOL_CTX_SIZE(%r6) + + _gpr_init SSX_NON_VOL_CTX_GPR, 14, 0x1414 + _gpr_init SSX_NON_VOL_CTX_GPR, 15, 0x1515 + _gpr_init SSX_NON_VOL_CTX_GPR, 16, 0x1616 + _gpr_init SSX_NON_VOL_CTX_GPR, 17, 0x1717 + _gpr_init SSX_NON_VOL_CTX_GPR, 18, 0x1818 + _gpr_init SSX_NON_VOL_CTX_GPR, 19, 0x1919 + _gpr_init SSX_NON_VOL_CTX_GPR, 20, 0x2020 + _gpr_init SSX_NON_VOL_CTX_GPR, 21, 0x2121 + _gpr_init SSX_NON_VOL_CTX_GPR, 22, 0x2222 + _gpr_init SSX_NON_VOL_CTX_GPR, 23, 0x2323 + _gpr_init SSX_NON_VOL_CTX_GPR, 24, 0x2424 + _gpr_init SSX_NON_VOL_CTX_GPR, 25, 0x2525 + _gpr_init SSX_NON_VOL_CTX_GPR, 26, 0x2626 + _gpr_init SSX_NON_VOL_CTX_GPR, 27, 0x2727 + _gpr_init SSX_NON_VOL_CTX_GPR, 28, 0x2828 + _gpr_init SSX_NON_VOL_CTX_GPR, 29, 0x2929 + _gpr_init SSX_NON_VOL_CTX_GPR, 30, 0x3030 + _gpr_init SSX_NON_VOL_CTX_GPR, 31, 0x3131 + + ## Initialization is done - the stack pointer is stored back in the + ## thread. + + stw %r6, SSX_THREAD_OFFSET_SAVED_STACK_POINTER(%r3) + blr + + .epilogue __ssx_thread_context_initialize + +/// \endcond diff --git a/src/ssx/ppc405/ssx_port_types.h b/src/ssx/ppc405/ssx_port_types.h new file mode 100755 index 0000000..f57951d --- /dev/null +++ b/src/ssx/ppc405/ssx_port_types.h @@ -0,0 +1,44 @@ +#ifndef __SSX_PORT_TYPES_H__ +#define __SSX_PORT_TYPES_H__ + +// $Id: ssx_port_types.h,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ssx_port_types.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_port_types.h +/// \brief Type definitions required by the SSX port. +/// +/// \todo GCC provides a portable version of cntlzw called __builtin_clz(). +/// We should make the SSX priority queues portable by using this facility. +/// +/// \todo I think that if more of the port-dependent types were moved here, we +/// could break the circular dependencies in some of the header inclusion and +/// simplify the way the SSX/port/chip headers are included. + +/// An SsxIrqId is an integer in the range of valid interrupts defined by the +/// interrupt controller. + +typedef uint8_t SsxIrqId; + +/// SSX requires the port to define the type SsxThreadQueue, which is a +/// priority queue (where 0 is the highest priority). This queue must be able +/// to handle SSX_THREADS + 1 priorities (the last for the idle thread). The +/// port must also define methods for clearing, insertion, deletion and min +/// (with assumed legal priorities). The min operation returns SSX_THREADS if +/// the queue is empty. (Or a queue could be initialized with the SSX_THREADS +/// entry always present - SSX code never tries to delete the idle thread from +/// a thread queue). +/// +/// These queues are used both for the run queue and the pending queue +/// associated with every semaphore. +/// +/// On PPC405 with 32 threads (implied), this is a job for a uint32_t and +/// cntlzw(). + +typedef uint32_t SsxThreadQueue; + +#endif /* __SSX_PORT_TYPES_H__ */ diff --git a/src/ssx/ppc405/ssxppc405files.mk b/src/ssx/ppc405/ssxppc405files.mk new file mode 100755 index 0000000..72d5ecb --- /dev/null +++ b/src/ssx/ppc405/ssxppc405files.mk @@ -0,0 +1,53 @@ +# $Id: ssxppc405files.mk,v 1.2 2014/06/26 13:00:55 cmolsen Exp $ +# $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ssxppc405files.mk,v $ +# @file ssxppc405files.mk +# +# @brief mk for including ppc405 object files +# +# @page ChangeLogs Change Logs +# @section ssxppc405files.mk +# @verbatim +# +# +# Change Log ****************************************************************** +# Flag Defect/Feature User Date Description +# ------ -------------- ---------- ------------ ----------- +# @pb00E pbavari 03/11/2012 Makefile ODE support +# +# @endverbatim +# +########################################################################## +# Include Files +########################################################################## + + + +########################################################################## +# Object Files +########################################################################## +PPC405-C-SOURCES = ppc405_core.c \ + ppc405_lib_core.c \ + ppc405_cache_core.c \ + ppc405_init.c \ + ppc405_irq_core.c \ + ppc405_irq_init.c + +PPC405-S-SOURCES = ppc405_boot.S \ + ppc405_exceptions.S \ + ppc405_cache_init.S \ + ppc405_mmu_asm.S \ + ppc405_breakpoint.S + +PPC405-TIMER-C-SOURCES = +PPC405-TIMER-S-SOURCES = + +PPC405-THREAD-C-SOURCES += +PPC405-THREAD-S-SOURCES += ppc405_thread_init.S + +PPC405-MMU-C-SOURCES += ppc405_mmu.c +PPC405-MMU-S-SOURCES += + +PPC405_OBJECTS += $(PPC405-C-SOURCES:.c=.o) $(PPC405-S-SOURCES:.S=.o) + + + diff --git a/src/ssx/ssx/Makefile b/src/ssx/ssx/Makefile new file mode 100755 index 0000000..ce1116f --- /dev/null +++ b/src/ssx/ssx/Makefile @@ -0,0 +1,25 @@ +# $Id: Makefile,v 1.2 2013/12/12 16:12:38 bcbrock Exp $ + +# This Makefile is designed to be invoked with the -I argument set to +# the location of the "ssx.mk" for the build + +include ../pgp/ssx.mk +include ssxssxfiles.mk + +ifeq "$(SSX_TIMER_SUPPORT)" "1" +SSX_OBJECTS += ${SSX-TIMER-C-SOURCES:.c=.o} +endif + +ifeq "$(SSX_THREAD_SUPPORT)" "1" +SSX_OBJECTS += ${SSX-THREAD-C-SOURCES:.c=.o} +endif + +all: $(SSX_OBJECTS) + +.PHONY : clean +clean: + rm -f *.o *.d *.d.* + +ifneq ($(MAKECMDGOALS),clean) +include $(SSX_OBJECTS:.o=.d) +endif diff --git a/src/ssx/ssx/ssx.h b/src/ssx/ssx/ssx.h new file mode 100755 index 0000000..5470968 --- /dev/null +++ b/src/ssx/ssx/ssx.h @@ -0,0 +1,126 @@ +#ifndef __SSX_H__ +#define __SSX_H__ + +// $Id: ssx.h,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx.h +/// \brief The combined header of the SSX kernel. +/// +/// This header will be included in any C or assembler source file that +/// requires any of the SSX API. All headers defined by SSX and co-compiled +/// code should be protected such that they can be included without error into +/// assembly. + +#ifndef __ASSEMBLER__ +#include <stdint.h> +#include <stddef.h> +#endif /* __ASSEMBLER__ */ + +#define __SSX__ + +/// The application environment specifies whether or not it will provide an +/// application configuration file, which must be named "ssx_app_cfg.h". + +#ifndef USE_SSX_APP_CFG_H +#define USE_SSX_APP_CFG_H 0 +#endif + +#if USE_SSX_APP_CFG_H +#include "ssx_app_cfg.h" +#endif + +#include "ssx_macros.h" +#include "ssx_api.h" +#include "ssx_port.h" +#include "ssx_kernel.h" +#include "ssx_io.h" + +#ifndef __ASSEMBLER__ + +#define MIN(X, Y) \ + ({ \ + typeof (X) __x = (X); \ + typeof (Y) __y = (Y); \ + (__x < __y) ? __x : __y; }) + +#define MAX(X, Y) \ + ({ \ + typeof (X) __x = (X); \ + typeof (Y) __y = (Y); \ + (__x > __y) ? __x : __y; \ + }) + +/// \todo These don't require 32/64 bit versions, can always promote 32->64. + +#define FLOOR_LOG2_32(x) (32 - 1 - cntlz32(x)) +#define FLOOR_LOG2_64(x) (64 - 1 - cntlz64(x)) + +#define CEILING_LOG2(x) \ + ({ \ + uint64_t __x = (uint64_t)(x); \ + int __y; \ + __y = FLOOR_LOG2_64(__x); \ + if ((__x & (__x - 1)) != 0) { \ + __y++; \ + } \ + __y;}) + + +#define POW2_32(x) ((uint32_t)1 << (x)) +#define POW2_64(x) ((uint64_t)1 << (x)) + +/// Cast a pointer to another type +/// +/// This macro is necessary when casting a pointer to a longer integer type. +/// The pointer is first cast to the equivalent integer type 'unsigned long', +/// then cast to the final type. You can also use this to cast integers longer +/// than pointers back to pointers. + +#define CAST_POINTER(t, p) ((t)((unsigned long)(p))) + + +/// Create an alignment attribute. +#define ALIGNED_ATTRIBUTE(alignment) __attribute__ ((aligned (alignment))) + +/// Create a specific-section attribute +/// +/// Note that the section \a s here must be a string. Also note that data +/// specified to reside in specific sections must always be +/// initialized. Otherwise it confuses the linker which wants to put +/// uninitialized data into .bss sections. +/// +/// \code +/// +/// int foo SECTION_ATTRIBUTE(".noncacheable") = 0; +/// int bar[10] SECTION_ATTRIBUTE(".noncacheable") = {0}; +/// +/// \endcode +#define SECTION_ATTRIBUTE(s) __attribute__ ((section (s))) + +/// Create a 'used' attribute +/// +/// This is required for example to avoid "function unused" warnings when a +/// function is declared static but only referenced by inline assembler: +/// +/// \code +/// +/// static USED_ATTRIBUTE void +/// _checkstop(void* arg, SsxIrqId irq, int priority) +/// { +/// SSX_PANIC(VALIDATION_CHECKSTOP); +/// } +/// +/// SSX_IRQ_FAST2FULL(_validationCheckstopHandler, _checkstop); +/// +/// \endcode +#define USED_ATTRIBUTE __attribute__ ((used)) + +#endif /* __ASSEMBLER__ */ + +#endif /* __SSX_H__ */ diff --git a/src/ssx/ssx/ssx_api.h b/src/ssx/ssx/ssx_api.h new file mode 100755 index 0000000..c9657e4 --- /dev/null +++ b/src/ssx/ssx/ssx_api.h @@ -0,0 +1,888 @@ +#ifndef __SSX_API_H__ +#define __SSX_API_H__ + +// $Id: ssx_api.h,v 1.2 2014/02/03 01:30:44 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_api.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_api.h +/// \brief Macros and declarations for the SSX API. + +// Basic constants + +/// Although the number of threads is defined as a manifest constant, +/// numerous parts of the SSX code assume this definition. The number of +/// supported threads _can not_ be changed simply by changing this constant. + +#define SSX_THREADS 32 + +#define SSX_IDLE_THREAD_PRIORITY SSX_THREADS + +// Interrupt API + +#define SSX_NONCRITICAL 0 +#define SSX_CRITICAL 1 +#define SSX_SUPERCRITICAL 2 + +#define SSX_IRQ_POLARITY_ACTIVE_LOW 0 +#define SSX_IRQ_POLARITY_ACTIVE_HIGH 1 + +#define SSX_IRQ_TRIGGER_LEVEL_SENSITIVE 0 +#define SSX_IRQ_TRIGGER_EDGE_SENSITIVE 1 + +// API return codes + +#define SSX_OK 0 +#define SSX_ILLEGAL_CONTEXT_CRITICAL_INTERRUPT 0x00779001 +#define SSX_ILLEGAL_CONTEXT_THREAD_CONTEXT 0x00779002 +#define SSX_ILLEGAL_CONTEXT_INTERRUPT_CONTEXT 0x00779003 +#define SSX_ILLEGAL_CONTEXT_THREAD 0x00779004 +#define SSX_ILLEGAL_CONTEXT_TIMER 0x00779005 +#define SSX_ILLEGAL_CONTEXT_PPC405_CACHE 0x00779006 +#define SSX_INVALID_THREAD_AT_RESUME1 0x00779007 +#define SSX_INVALID_THREAD_AT_RESUME2 0x00779008 +#define SSX_INVALID_THREAD_AT_SUSPEND1 0x00779009 +#define SSX_INVALID_THREAD_AT_SUSPEND2 0x0077900a +#define SSX_INVALID_THREAD_AT_DELETE 0x0077900b +#define SSX_INVALID_THREAD_AT_INFO 0x0077900c +#define SSX_INVALID_THREAD_AT_CHANGE 0x0077900d +#define SSX_INVALID_THREAD_AT_SWAP1 0x0077900e +#define SSX_INVALID_THREAD_AT_SWAP2 0x0077900f +#define SSX_INVALID_THREAD_AT_CREATE 0x00779010 +#define SSX_INVALID_SEMAPHORE_AT_POST 0x00779011 +#define SSX_INVALID_SEMAPHORE_AT_PEND 0x00779012 +#define SSX_INVALID_SEMAPHORE_AT_RELEASE 0x00779013 +#define SSX_INVALID_SEMAPHORE_AT_INFO 0x00779014 +#define SSX_INVALID_SEMAPHORE_AT_CREATE 0x00779015 +#define SSX_INVALID_TIMER_AT_SCHEDULE 0x00779016 +#define SSX_INVALID_TIMER_AT_CANCEL 0x00779017 +#define SSX_INVALID_TIMER_AT_INFO 0x00779018 +#define SSX_INVALID_TIMER_AT_CREATE 0x00779019 +#define SSX_INVALID_ARGUMENT_IRQ_SETUP 0x0077901a +#define SSX_INVALID_ARGUMENT_IRQ_HANDLER 0x0077901b +#define SSX_INVALID_ARGUMENT_INTERRUPT 0x00779024 +#define SSX_INVALID_ARGUMENT_CONTEXT_SET 0x00779025 +#define SSX_INVALID_ARGUMENT_CONTEXT_GET 0x00779026 +#define SSX_INVALID_ARGUMENT_PPC405_FIT 0x00779027 +#define SSX_INVALID_ARGUMENT_PPC405_WATCHDOG 0x00779028 +#define SSX_INVALID_ARGUMENT_INIT 0x00779029 +#define SSX_INVALID_ARGUMENT_SEMAPHORE 0x0077902a +#define SSX_INVALID_ARGUMENT_THREAD_CHANGE 0x0077902b +#define SSX_INVALID_ARGUMENT_THREAD_PRIORITY 0x0077902c +#define SSX_INVALID_ARGUMENT_THREAD1 0x0077902d +#define SSX_INVALID_ARGUMENT_THREAD2 0x0077902e +#define SSX_INVALID_ARGUMENT_THREAD3 0x0077902f +#define SSX_STACK_OVERFLOW 0x00779030 +#define SSX_TIMER_ACTIVE 0x00779031 +#define SSX_TIMER_NOT_ACTIVE 0x00779032 +#define SSX_PRIORITY_IN_USE_AT_RESUME 0x00779033 +#define SSX_PRIORITY_IN_USE_AT_CHANGE 0x00779034 +#define SSX_PRIORITY_IN_USE_AT_SWAP 0x00779035 +#define SSX_SEMAPHORE_OVERFLOW 0x00779036 +#define SSX_SEMAPHORE_PEND_NO_WAIT 0x00779037 +#define SSX_SEMAPHORE_PEND_TIMED_OUT 0x00779038 +#define SSX_SEMAPHORE_PEND_WOULD_BLOCK 0x00779039 +#define SSX_INVALID_DEQUE_SENTINEL 0x0077903a +#define SSX_INVALID_DEQUE_ELEMENT 0x0077903b +#define SSX_INVALID_OBJECT 0x0077903c + +// Kernel panics + +#define SSX_NO_TIMER_SUPPORT 0x0077903d +#define SSX_START_THREADS_RETURNED 0x0077903e +#define SSX_UNIMPLEMENTED 0x0077903f +#define SSX_SCHEDULING_INVARIANT 0x00779040 +#define SSX_TIMER_HANDLER_INVARIANT 0x00779041 +#define SSX_THREAD_TIMEOUT_STATE 0x00779045 + + +/// \defgroup ssx_thread_states SSX Thread States +/// +/// Threads are created in the state SSX_THREAD_STATE_SUSPENDED_RUNNABLE. +/// When the thread is mapped it transitions to state SSX_THREAD_STATE_MAPPED. +/// A mapped thread is runnable if it appears in the run queue; there is no +/// other flag or status to indicate a runnable thread. If a blocked thread +/// is suspended it goes into state SSX_THREAD_STATE_SUSPENDED_BLOCKED. For +/// all threads the reason for blockage is detailed in the \a flags field of +/// the thread; See \ref ssx_thread_flags. SSX_THREAD_STATE_DELETED and +/// SSX_THREAD_STATE_COMPLETED are effectively equivalent but named +/// individually for reporting purposes. +/// +/// \note This separation of the thread \a state and \a flags allows the use +/// of an SSX semaphore as a thread barrier, as it supports a non-iterative +/// implementation of ssx_semaphore_release_all() in which all threads blocked +/// on the semaphore are simultaneously inserted into the run queue with an +/// atomic operation, followed by each individual thread readjusting its flags +/// appropriately once the thread runs again. +/// +/// @{ + +#define SSX_THREAD_STATE_SUSPENDED_RUNNABLE 1 +#define SSX_THREAD_STATE_MAPPED 2 +#define SSX_THREAD_STATE_SUSPENDED_BLOCKED 3 +#define SSX_THREAD_STATE_COMPLETED 4 +#define SSX_THREAD_STATE_DELETED 5 + +/// @} + + +/// \defgroup ssx_thread_flags SSX Thread Flags +/// +/// The \a flag field of the thread extends the information contained in the +/// \a state field; See \ref ssx_thread_states. Blocked threads will show +/// SSX_THREAD_FLAG_SEMAPHORE_PEND, SSX_THREAD_FLAG_TIMER_PEND or both (if +/// blocked on a semaphore with timeout). The flag SSX_THREAD_FLAG_TIMED_OUT +/// indicates that a thread timer timed out before the thread became +/// runnable. Currently only the semaphore-pend-with-timeout code uses this +/// flag. +/// +/// Note that a thread can be mapped and runnable (in the run queue) even +/// though SSX_THREAD_FLAG_SEMAPHORE_PEND and/or SSX_THREAD_FLAG_TIMER_PEND +/// are set. These flags are always cleared by the thread itself, not the code +/// that unblocks the thread. This allows the implementation of the +/// ssx_semaphore_release_all() as explained in \ref ssx_thread_states. +/// +/// @{ + +#define SSX_THREAD_FLAG_SEMAPHORE_PEND 0x1 +#define SSX_THREAD_FLAG_TIMER_PEND 0x2 +#define SSX_THREAD_FLAG_TIMED_OUT 0x4 + +/// @} + + +// Critical Sections + +/// Enter a critical section of a given priority, saving the current machine +/// context. + +#define ssx_critical_section_enter(priority, pctx) \ + ssx_interrupt_disable(priority, pctx) + +/// Exit a critical section by restoring the previous machine context. + +#define ssx_critical_section_exit(pctx) \ + ssx_machine_context_set(pctx) + + +/// Execute a statement atomically, in a particular interrupt priority +/// context. + +#define SSX_ATOMIC(priority, stmt) \ + do { \ + SsxMachineContext __ctx; \ + ssx_critical_section_enter((priority), &__ctx); \ + stmt; \ + ssx_critical_section_exit(&__ctx); \ + } while (0) + + +// Application-overrideable definitions + +/// Control whether or not the API functions check for errors. +/// +/// This definition can be overriden by the application. + +#ifndef SSX_ERROR_CHECK_API +#define SSX_ERROR_CHECK_API 1 +#endif + +/// Control whether API errors cause kernel panics or return negative error +/// codes. +/// +/// This selection is only valid if \c SSX_ERROR_CHECK_API is defined +/// non-0. This definition can be overriden by the application. + +#ifndef SSX_ERROR_PANIC +#define SSX_ERROR_PANIC 1 +#endif + +/// Control whether or not the SSX kernel checks key invariants. +/// +/// Violations of kernel invariants always cause kernel panics. This +/// definition can be overriden by the application. + +#ifndef SSX_ERROR_CHECK_KERNEL +#define SSX_ERROR_CHECK_KERNEL 1 +#endif + +/// Define the time interval type, which must be an unsigned type of a size +/// less then or equal to the size of \c SsxTimebase. This definition can be +/// overridden by the application. + +#ifndef SSX_TIME_INTERVAL_TYPE +#define SSX_TIME_INTERVAL_TYPE uint32_t +#endif + +/// Provide support for the SsxTimer APIs in addition to the default +/// initerrupt APIs. This definition can be overridden by the application. + +#ifndef SSX_TIMER_SUPPORT +#define SSX_TIMER_SUPPORT 1 +#endif + +/// Provide support for the all SSX APIs. Thread support requires/implies +/// support for time services and semaphores. This definition can be +/// overridden by the application. + +#ifndef SSX_THREAD_SUPPORT +#define SSX_THREAD_SUPPORT 1 +#endif + +/// Control the level of stack checking. +/// +/// This definition can be overriden by the application. +/// +/// 0 : No stack prepatterning or checking is made for thread and kernel +/// stacks. +/// +/// 1 : Kernel interrupt stacks are prepatterned during +/// \c ssx_initialize(). Thread stacks are prepatterned during +/// \c ssx_thread_create(). +/// +/// 2 : (\b Default - Currently Unimplemented) In addition to prepatterning, +/// stack utilization is computed at the exit of context switches and +/// noncritical interrupt processing. The maximum utilization is stored in +/// the thread data structure. The kernel will panic if stack overflow is +/// detected. Stack utilization is not computed for the idle thread. + +#ifndef SSX_STACK_CHECK +#define SSX_STACK_CHECK 1 +#endif + +/// A hook for main() +/// +/// This hook macro is expanded in the body of __ssx_main() prior to the call +/// of the application main(). The application can redefine this hook macro +/// in (or in headers referred to in) the application header +/// ssx_app_cfg.h. The SSX_MAIN_HOOK will run on the stack of main(). + +#ifndef SSX_MAIN_HOOK +#define SSX_MAIN_HOOK do {} while (0) +#endif + +/// A hook for ssx_start_threads() +/// +/// This hook macro is expanded in the call-tree of ssx_start_threads() before +/// threads are actually started. The application can redefine this hook +/// macro in (or in headers referred to in) the application header +/// ssx_app_cfg.h. +/// +/// The SSX_START_THREADS_HOOK runs as a pseudo-interrupt handler on the +/// noncritical interrupt stack, with noncritical interrupts disabled. + +#ifndef SSX_START_THREADS_HOOK +#define SSX_START_THREADS_HOOK do {} while (0) +#endif + +/// The maximum value of the \c SsxTimebase type. + +#define SSX_TIMEBASE_MAX ((SsxTimebase)-1) + +/// A special value that specifies that the timebase will not be reset during +/// ssx_init(). + +#define SSX_TIMEBASE_CONTINUES SSX_TIMEBASE_MAX + +/// By convention, a timeout value indicating 'no waiting' in a call of \c +/// ssx_semaphore_pend(). + +#define SSX_NO_WAIT 0 + +/// By convention, a timeout value indicating 'wait forever' in a call of \c +/// ssx_semaphore_pend(). + +#define SSX_WAIT_FOREVER ((SsxInterval)-1) + +/// The SSX timebase frequency in Hz +/// +/// Earlier version of SSX defined the timbase frequency as a preprocessor +/// macro. Now, the timebase frequency is specified as a parameter of the +/// ssx_initialize() API. The macro remains defined for backwards +/// compatibility, however all kernel uses of the timebase frequency are now +/// optimized around the timebase parameter. + +#define SSX_TIMEBASE_FREQUENCY_HZ __ssx_timebase_frequency_hz + +/// Convert a time in integral seconds to a time interval - overflows are +/// ignored. The application can redefine this macro. + +#ifndef SSX_SECONDS +#define SSX_SECONDS(s) ((SsxInterval)(__ssx_timebase_frequency_hz * (SsxInterval)(s))) +#endif + +/// Convert a time in integral milliseconds to a time interval - overflows are +/// ignored, and a frequency evenly (or closely) divisible by 1000 is +/// assumed. The application can redefine this macro. + +#ifndef SSX_MILLISECONDS +#define SSX_MILLISECONDS(m) ((SsxInterval)(__ssx_timebase_frequency_khz * (SsxInterval)(m))) +#endif + +/// Convert a time in integral microseconds to a time interval - overflows are +/// ignored, and a frequncy evenly (or closely) divisible by 1,000,000 is +/// assumed. The application can redefine this macro. + +#ifndef SSX_MICROSECONDS +#define SSX_MICROSECONDS(u) ((SsxInterval)(__ssx_timebase_frequency_mhz * (SsxInterval)(u))) +#endif + +/// Convert a time in integral nanoseconds to a time interval - overflows are +/// ignored, and a frequeyncy evenly (or closely) divisible by 1,000,000 is +/// assumed. The application can redefine this macro. + +#ifndef SSX_NANOSECONDS +#define SSX_NANOSECONDS(n) \ + ((SsxInterval)((__ssx_timebase_frequency_mhz * (SsxInterval)(n)) / 1000)) +#endif + + +// Application and kernel tracing. Tracing can only be enabled if the port +// defines the trace macros in that case. + +/// Enable SSX application tracing +#ifndef SSX_TRACE_ENABLE +#define SSX_TRACE_ENABLE 0 +#endif + +/// Enable SSX kernel tracing +#ifndef SSX_KERNEL_TRACE_ENABLE +#define SSX_KERNEL_TRACE_ENABLE 0 +#endif + +#if !SSX_TRACE_ENABLE +#define SSX_TRACE(event) +#endif + +#if !SSX_KERNEL_TRACE_ENABLE + +#define SSX_TRACE_THREAD_SLEEP(priority) +#define SSX_TRACE_THREAD_WAKEUP(priority) +#define SSX_TRACE_THREAD_SEMAPHORE_PEND(priority) +#define SSX_TRACE_THREAD_SEMAPHORE_POST(priority) +#define SSX_TRACE_THREAD_SEMAPHORE_TIMEOUT(priority) +#define SSX_TRACE_THREAD_SUSPENDED(priority) +#define SSX_TRACE_THREAD_DELETED(priority) +#define SSX_TRACE_THREAD_COMPLETED(priority) +#define SSX_TRACE_THREAD_MAPPED_RUNNABLE(priority) +#define SSX_TRACE_THREAD_MAPPED_SEMAPHORE_PEND(priority) +#define SSX_TRACE_THREAD_MAPPED_SLEEPING(priority) + + +#endif /* SSX_KERNEL_TRACE_ENABLE */ + + +#ifndef __ASSEMBLER__ + +#include <stddef.h> +#include <stdint.h> + +/// The timebase frequency in Hz; A parameter to ssx_initialize() +extern uint32_t __ssx_timebase_frequency_hz; + +/// The timebase frequency in KHz +extern uint32_t __ssx_timebase_frequency_khz; + +/// The timebase frequency in Mhz +extern uint32_t __ssx_timebase_frequency_mhz; + + +typedef unsigned long int SsxAddress; + +typedef uint8_t SsxThreadState; + +typedef uint8_t SsxThreadPriority; + +typedef uint8_t SsxThreadFlags; + +typedef uint32_t SsxSemaphoreCount; + +typedef uint64_t SsxTimebase; + +typedef SSX_TIME_INTERVAL_TYPE SsxInterval; + +#include "ssx_port_types.h" + +typedef struct { + + /// A priority queue of threads pending on the semaphore. + SsxThreadQueue pending_threads; + + /// The current semaphore count. + SsxSemaphoreCount count; + + /// The maximum allowable count - for error checking. + SsxSemaphoreCount max_count; + +} SsxSemaphore; + + +/// Compile-time initialize an SsxSemaphore structure +/// +/// This low-level macro creates a structure initializatin of an SsxSemaphore +/// structure. This can be used for example to create compile-time initialized +/// arrays of semaphores. +#define SSX_SEMAPHORE_INITIALIZATION(_initial_count, _max_count) \ + {.pending_threads = 0, \ + .count = (_initial_count), \ + .max_count = (_max_count)} + + +/// Declare and initialize a semaphore +#define SSX_SEMAPHORE(sem, initial_count, max_count) \ + SsxSemaphore sem = SSX_SEMAPHORE_INITIALIZATION(initial_count, max_count) + + +/// A generic doubly-linked list object +/// +/// This object functions both as a sentinel mode for a deque as well as a +/// pointer container for elements in deques. The SSX API assumes that +/// queueable structures will be defined with an SsxDeque structure as the +/// initial 'data member' of the structure. This allows a pointer to a queue +/// element to be cast to a pointer to an SsxDeque and vice-versa. + +typedef struct SsxDeque { + + /// Pointer to the head or the next element in a deque. + /// + /// When an SsxDeque is used as the sentinel node for a queue, \a next + /// points to the head of the queue, and the condition (next == \<self\>) + /// indicates an empty SsxDeque. By convention the condition (\a next == + /// 0) is used to indicate that a queue element is not enqueued. + struct SsxDeque* next; + + /// Pointer to the tail or previous element in a deque. + /// + /// When a DQueue is used as the sentinel node for a queue, \a previous + /// points to the tail of the queue. + struct SsxDeque* previous; + +} SsxDeque; + + +typedef void (*SsxTimerCallback)(void *); + +#define SSX_TIMER_CALLBACK(callback) void callback(void *) + +struct SsxTimer; + +/// The SSX timer object + +typedef struct SsxTimer { + + /// The time queue management pointers + /// + /// This pointer container is defined as the first element of the + /// structure to allow the SsxTimer to be cast to an SsxDeque and + /// vice-versa. + SsxDeque deque; + + /// The absolute timeout of the timer. + SsxTimebase timeout; + + /// The timer period + /// + /// If not 0, then this is a periodic timer and it will be automatically + /// rescheduled in absolute time from the previous timeout. + SsxInterval period; + + /// The timer callback + /// + /// For SSX thread timers used to implement Sleep and semaphore pend + /// timeouts this field is initialized to __ssx_thread_timeout(). + SsxTimerCallback callback; + + /// Private data passed to the callback. + /// + /// For SSX thread timers used to implement Sleep and semaphore pend this + /// field is initialized to a pointer to the thread. + void *arg; + + /// Options for timer processing; See \ref ssx_timer_options + uint8_t options; + +} SsxTimer; + +/// \defgroup ssx_timer_options SSX Timer Options +/// @{ + +/// Allow interrupt preemption during the callback +/// +/// This is the normal mode for SsxTimer objects scheduled by SSX kernal +/// mechanisms. The timer callbacks effectively run as if inside a +/// highest-priority thread, allowing other interrupts to preempt them. +#define SSX_TIMER_CALLBACK_PREEMPTIBLE 0x1 + +/// @} + + +// Threads + +typedef void (*SsxThreadRoutine)(void *arg); + +#define SSX_THREAD_ROUTINE(f) void f(void *arg); + +typedef struct { + + /// Stack pointer saved during context switches. Assembler code expects + /// this to always be at address offset 0 from the thread pointer. + SsxAddress saved_stack_pointer; + + /// This is 1 past the last valid byte address of the thread stack. + /// Assembler code expects this to always be at address offset (sizeof + /// SsxAddress) from the thread pointer. + SsxAddress stack_limit; + + /// This is the original base of the stack. + /// Assembler code expects this to always be at address offset 2 * (sizeof + /// SsxAddress) from the thread pointer. + SsxAddress stack_base; + + /// If the thread is blocked on a semaphore, then this is the semaphore the + /// thread is blocked on. + SsxSemaphore *semaphore; + + /// The thread priority. + SsxThreadPriority priority; + + /// The thread state; See \ref ssx_thread_states + SsxThreadState state; + + /// Thread flags; See \ref ssx_thread_flags + SsxThreadFlags flags; + + /// The timer structure handles Sleep and blocking on a semaphore with + /// timeout. + SsxTimer timer; + +} SsxThread; + + +// Initialization APIs + +int +ssx_initialize(SsxAddress noncritical_stack, + size_t noncritical_stack_size, + SsxAddress critical_stack, + size_t critical_stack_size, + SsxTimebase initial_timebase, + uint32_t timebase_frequency_hz); + + +// Timebase APIs + +SsxTimebase +ssx_timebase_get(void); + +void +ssx_timebase_set(SsxTimebase timebase); + +// Interrupt preemption APIs + +int +ssx_interrupt_preemption_enable(void); + +int +ssx_interrupt_preemption_disable(void); + +// Timer APIs + +int +ssx_timer_create(SsxTimer *timer, + SsxTimerCallback callback, + void *arg); + +int +ssx_timer_create_nonpreemptible(SsxTimer *timer, + SsxTimerCallback callback, + void *arg); + +int +ssx_timer_schedule_absolute(SsxTimer *timer, + SsxTimebase time, + SsxInterval period); + +int +ssx_timer_schedule(SsxTimer *timer, + SsxInterval interval, + SsxInterval period); + +int +ssx_timer_cancel(SsxTimer *timer); + +int +ssx_timer_info_get(SsxTimer *timer, + SsxTimebase *timeout, + int *active); + +// Thread APIs + +int +ssx_thread_create(SsxThread *thread, + SsxThreadRoutine thread_routine, + void *arg, + SsxAddress stack, + size_t stack_size, + SsxThreadPriority priority); + +int +ssx_start_threads(void); + +int +ssx_thread_resume(SsxThread *thread); + +int +ssx_thread_suspend(SsxThread *thread); + +int +ssx_thread_delete(SsxThread *thread); + +int +ssx_complete(void); + +int +ssx_sleep_absolute(SsxTimebase time); + +int +ssx_sleep(SsxInterval interval); + +int +ssx_thread_info_get(SsxThread *thread, + SsxThreadState *state, + SsxThreadPriority *priority, + int *runnable); + +int +ssx_thread_priority_change(SsxThread *thread, + SsxThreadPriority new_priority, + SsxThreadPriority *old_priority); + +int +ssx_thread_at_priority(SsxThreadPriority priority, + SsxThread **thread); + +int +ssx_thread_priority_swap(SsxThread* thread_a, SsxThread* thread_b); + + +// Semaphore APIs + +int +ssx_semaphore_create(SsxSemaphore *semaphore, + SsxSemaphoreCount initial_count, + SsxSemaphoreCount max_count); + +int +ssx_semaphore_post(SsxSemaphore *semaphore); + +int +ssx_semaphore_pend(SsxSemaphore *semaphore, + SsxInterval timeout); + +int +ssx_semaphore_release_all(SsxSemaphore *semaphore); + + +int +ssx_semaphore_info_get(SsxSemaphore *semaphore, + SsxSemaphoreCount *count, + int *pending); + +void +ssx_semaphore_post_handler(void *arg, + SsxIrqId irq, + int priority); + +// Misc. APIs + +void +ssx_halt() __attribute__ ((noreturn)); + +// Deque APIs + +int +ssx_deque_sentinel_create(SsxDeque *deque); + +int +ssx_deque_element_create(SsxDeque *element); + + +/// Check for an empty SsxDeque +/// +/// \param deque The sentinel node of a deque +/// +/// \retval 0 The SsxDeque is not empty +/// +/// \retval 1 The SsxDeque is empty + +static inline int +ssx_deque_is_empty(SsxDeque *deque) +{ + return (deque == deque->next); +} + + +/// Check if an SsxDeque element is currently enqueued +/// +/// \param element Typically the SsxDeque object of a queable structure +/// +/// \retval 0 The element is not currently enqueued +/// +/// \retval 1 The element is currently enqueued + +static inline int +ssx_deque_is_queued(SsxDeque *element) +{ + return (element->next != 0); +} + + +/// Append an element to the tail of a deque (FIFO order) +/// +/// \param deque The sentinel node of a deque +/// +/// \param element Typically the SsxDeque object of a queable structure +/// +/// It is an error to call this API on an element that is already enqueued, +/// but the API does not check for this error. + +static inline void +ssx_deque_push_back(SsxDeque *deque, SsxDeque *element) +{ + deque->previous->next = element; + element->previous = deque->previous; + element->next = deque; + deque->previous = element; +} + + +/// Push an element at the head of a deque (LIFO order) +/// +/// \param deque The sentinel node of a deque +/// +/// \param element Typically the SsxDeque object of a queable structure +/// +/// It is an error to call this API on an element that is already enqueued, +/// but the API does not check for this error. + +static inline void +ssx_deque_push_front(SsxDeque *deque, SsxDeque *element) +{ + deque->next->previous = element; + element->next = deque->next; + element->previous = deque; + deque->next = element; +} + +/// Pop an element from the head of a deque +/// +/// \param deque The sentinel node of a deque +/// +/// \retval 0 The SsxDeque was empty prior to the call +/// +/// \retval non-0 A pointer to the previous head of the deque, which has been +/// removed from the deque and marked as no longer queued. + +// The cast of 'head' is used to remove the 'volatile' attribute. + +static inline SsxDeque * +ssx_deque_pop_front(SsxDeque *deque) +{ + SsxDeque *head; + + if (ssx_deque_is_empty(deque)) { + return 0; + } else { + head = (SsxDeque *)(deque->next); + deque->next = head->next; + deque->next->previous = deque; + head->next = 0; + return head; + } +} + + +/// Remove a deque element from any position in the deque +/// +/// \param element Typically the SsxDeque object of a queable structure +/// +/// It is an error to call this API on an element that is not currently +/// enqueued, but the API does not check for this error. + +static inline void +ssx_deque_delete(SsxDeque *element) +{ + element->previous->next = element->next; + element->next->previous = element->previous; + element->next = 0; +} + + +/// Cast a pointer to another type, in a way that won't cause warnings + +#define SSX_CAST_POINTER(t, p) ((t)((SsxAddress)(p))) + + +/// \page ssx_errors SSX API and Kernel Error Handling +/// +/// Error checking in the SSX API consumes a significant amount of code space. +/// Approximately 20% of the object code in the PPC405 port is devoted to +/// error checking. Presumably a like amount of time overhead is also added to +/// SSX API calls by this checking. +/// +/// API error checking can be disabled to save space and time in the kernel. +/// API errors can also be configured to cause kernel panics, allowing +/// applications to be coded without the overhead of error checking but still +/// providing an escape in the event of application errors or (unlikely) +/// hardware failures. The SSX default is to check for API errors and kernel +/// invariants, and panic should errors occur. +/// +/// SSX follows the Unix convention that a successful call of an API returns 0 +/// (SSX_OK), but returns a negative code in the event of failure, or to +/// provide further information. The error codes are all defined as manifest +/// constants. +/// +/// Some negative codes returned by SSX APIs are not considered errors. These +/// conditions are always checked, never cause a panic if they occur, and +/// their interpretation is always left to the application. See the detailed +/// documentation for each API for lists of error and non-error codes returned +/// by the API. +/// +/// There are three configuration options that control error handling in the +/// SSX API and kernel: +/// +/// \c SSX_ERROR_CHECK_API +/// +/// \arg \b 0 - No SSX API error checking. APIs that potentially return error +/// codes will always return 0 (SSX_OK) instead of an error code. Those +/// APIs that return negative codes that are not errors (see Table 1.5) +/// always return the negative non-error codes when appropriate. +/// +/// \arg \b 1 - (Default) All SSX API errors are checked. The behavior in +/// the event of an error is defined by the configuration option +/// SSX_ERROR_PANIC. +/// +/// \c SSX_ERROR_CHECK_KERNEL +/// +/// \arg \b 0 - No kernel invariant error checking is done. +/// +/// \arg \b 1 - (Default) Selected kernel invariants are checked. The overhead +/// for these checks should be minimal. +/// +/// \c SSX_ERROR_PANIC +/// +/// \arg \b 0 - SSX API calls return negative error codes in the event of +/// errors. Note that SSX kernel invariants always cause a panic if +/// violations occur. +/// +/// \arg \b 1 - (Default) In the event of errors SSX APIs invoke SSX_PANIC(code), +/// where code is a positive error code. Kernel invariant checks always +/// cause a panic if violations are detected. + +#endif /* __ASSEMBLER__ */ + +#endif /* __SSX_API_H__ */ diff --git a/src/ssx/ssx/ssx_core.c b/src/ssx/ssx/ssx_core.c new file mode 100755 index 0000000..7fa484a --- /dev/null +++ b/src/ssx/ssx/ssx_core.c @@ -0,0 +1,81 @@ +// $Id: ssx_core.c,v 1.2 2014/02/03 01:30:44 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_core.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_core.c +/// \brief Core routines for the SSX kernel. +/// +/// The entry points in this file are routines that are expected to be needed +/// at runtime by all SSX applications. This file also serves as a place for +/// kernel global variables to be realized. + +#define __SSX_CORE_C__ + +#include "ssx.h" + +#if !SSX_TIMER_SUPPORT + +/// If there is no timer support, then any call of the timer interrupt handler +/// is considered a fatal error. + +void +__ssx_timer_handler() +{ + SSX_PANIC(SSX_NO_TIMER_SUPPORT); +} + +#endif /* SSX_TIMER_SUPPORT */ + + +/// Initialize an SsxDeque sentinel node +/// +/// \param deque The sentinel node of the deque +/// +/// SSX has no way of knowing whether the \a deque is currently in use, so +/// this API must only be called on unitialized or otherwise unused sentinel +/// nodes. +/// +/// \retval 0 success +/// +/// \retval -SSX_INVALID_DEQUE_SENTINEL The \a deque pointer was null + +int +ssx_deque_sentinel_create(SsxDeque *deque) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(deque == 0, SSX_INVALID_DEQUE_SENTINEL); + } + + deque->next = deque->previous = deque; + return 0; +} + + +/// Initialize an SsxDeque element +/// +/// \param element Typically the SsxDeque object of a queable structure +/// +/// SSX has no way of knowing whether the \a element is currently in use, so +/// this API must only be called on unitialized or otherwise unused deque +/// elements. +/// +/// \retval 0 success +/// +/// \retval -SSX_INVALID_DEQUE_ELEMENT The \a element pointer was null + +int +ssx_deque_element_create(SsxDeque *element) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(element == 0, SSX_INVALID_DEQUE_ELEMENT); + } + + element->next = 0; + return 0; +} + +#undef __SSX_CORE_C__ diff --git a/src/ssx/ssx/ssx_init.c b/src/ssx/ssx/ssx_init.c new file mode 100755 index 0000000..fc12a9b --- /dev/null +++ b/src/ssx/ssx/ssx_init.c @@ -0,0 +1,159 @@ +// $Id: ssx_init.c,v 1.2 2014/02/03 01:30:44 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_init.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_init.c +/// \brief SSX initialization +/// +/// The entry points in this file are initialization routines - they are never +/// needed after SSX initialization and their code space could be reclaimed by +/// the application after initialization if required. + +#include "ssx.h" + +uint32_t __ssx_timebase_frequency_hz; +uint32_t __ssx_timebase_frequency_khz; +uint32_t __ssx_timebase_frequency_mhz; + + +/// Initialize SSX. +/// +/// \param noncritical_stack A stack area for noncritical interrupt handlers. +/// +/// \param noncritical_stack_size The size (in bytes) of the stack area for +/// noncritical interrupt handlers. +/// +/// \param critical_stack A stack area for critical interrupt handlers. +/// +/// \param critical_stack_size The size (in bytes) of the stack area for +/// critical interrupt handlers. +/// +/// \param initial_timebase The initial value of the SSX timebase. If this +/// argument is given as the special value \c SSX_TIMEBASE_CONTINUE, then the +/// timebase is not reset. +/// +/// \param timebase_frequency_hz The frequency of the SSX timebase in Hz. +/// +/// This routine \e must be called before any other SSX / routines, and \e +/// should be called before any interrupts are enabled. +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_ARGUMENT_INIT A stack pointer is 0 or is given +/// a 0 size. +/// +/// \retval -SSX_STACK_OVERFLOW One or both stacks are not large enough to +/// support a minimum context save in the event of an interrupt. + +// Note that SSX does not rely on any static initialization of dynamic +// variables. In debugging sessions using RAM-resident SSX images it is +// assumed that the processor may be reset at any time, so we always need to +// reset everything at initialization. + +int +ssx_initialize(SsxAddress noncritical_stack, + size_t noncritical_stack_size, + SsxAddress critical_stack, + size_t critical_stack_size, + SsxTimebase initial_timebase, + uint32_t timebase_frequency_hz) +{ + int rc; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((noncritical_stack == 0) || + (noncritical_stack_size == 0) || + (critical_stack == 0) || + (critical_stack_size == 0), + SSX_INVALID_ARGUMENT_INIT); + } + + if (initial_timebase != SSX_TIMEBASE_CONTINUES) { + __ssx_timebase_set(initial_timebase); + } + + __ssx_timebase_frequency_hz = timebase_frequency_hz; + __ssx_timebase_frequency_khz = timebase_frequency_hz / 1000; + __ssx_timebase_frequency_mhz = timebase_frequency_hz / 1000000; + + __ssx_thread_machine_context_default = SSX_THREAD_MACHINE_CONTEXT_DEFAULT; + + rc = __ssx_stack_init(&noncritical_stack, &noncritical_stack_size); + if (rc) { + return rc; + } + + __ssx_noncritical_stack = noncritical_stack; + __ssx_noncritical_stack_size = noncritical_stack_size; + + rc = __ssx_stack_init(&critical_stack, &critical_stack_size); + if (rc) { + return rc; + } + + __ssx_critical_stack = critical_stack; + __ssx_critical_stack_size = critical_stack_size; + +#if SSX_TIMER_SUPPORT + + // Initialize the time queue sentinel as a circular queue, set the next + // timeout and clear the cursor. + + ssx_deque_sentinel_create((SsxDeque*)&__ssx_time_queue); + __ssx_time_queue.cursor = 0; + __ssx_time_queue.next_timeout = SSX_TIMEBASE_MAX; + +#endif /* SSX_TIMER_SUPPORT */ + +#if SSX_THREAD_SUPPORT + + // Clear the priority map. The final entry [SSX_THREADS] is for the idle + // thread. + + int i; + for (i = 0; i <= SSX_THREADS; i++) { + __ssx_priority_map[i] = 0; + } + + // Initialize the thread scheduler + + __ssx_thread_queue_clear(&__ssx_run_queue); + __ssx_current_thread = 0; + __ssx_next_thread = 0; + __ssx_delayed_switch = 0; + +#endif /* SSX_THREAD_SUPPORT */ + + return SSX_OK; +} + + +/// Call the application main() +/// +/// __ssx_main() is called from the bootloader. It's only purpose is to +/// provide a place for the SSX_MAIN_HOOK to be called before main() is +/// called. + +void +__ssx_main(int argc, char **argv) +{ + SSX_MAIN_HOOK; + + int main(int argc, char **argv); + main(argc, argv); +} + + + + + + + + + diff --git a/src/ssx/ssx/ssx_kernel.h b/src/ssx/ssx/ssx_kernel.h new file mode 100755 index 0000000..c6a70ca --- /dev/null +++ b/src/ssx/ssx/ssx_kernel.h @@ -0,0 +1,281 @@ +#ifndef __SSX_KERNEL_H__ +#define __SSX_KERNEL_H__ + +// $Id: ssx_kernel.h,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_kernel.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_kernel.h +/// \brief SSX portable kernel (non-API) data and data structures +/// +/// \todo In theory, as long as the critical section entry/exit macros use GCC +/// memory barriers, we should be able to eliminate all of the 'volatile' +/// declarations in SSX code. These have been added to the PPC405 port, so +/// we should try it. + +#ifdef __SSX_CORE_C__ +#define IF__SSX_CORE_C__(x) x +#define UNLESS__SSX_CORE_C__(x) +#else +#define IF__SSX_CORE_C__(x) +#define UNLESS__SSX_CORE_C__(x) x +#endif + +#if SSX_MINIMIZE_KERNEL_CODE_SPACE +#define IF_SSX_MINIMIZE_KERNEL_CODE_SPACE(x) x +#define UNLESS_SSX_MINIMIZE_KERNEL_CODE_SPACE(x) +#else +#define IF_SSX_MINIMIZE_KERNEL_CODE_SPACE(x) +#define UNLESS_SSX_MINIMIZE_KERNEL_CODE_SPACE(x) x +#endif + + +#ifndef __ASSEMBLER__ + +/// This is the stack pointer saved when switching from a thread or +/// non-critical interrupt context to a full-mode critical interrupt context. + +UNLESS__SSX_CORE_C__(extern) +volatile +SsxAddress __ssx_saved_sp_critical; + +/// The critical interrupt stack; constant once defined by the call of +/// ssx_initialize(). + +UNLESS__SSX_CORE_C__(extern) +volatile +SsxAddress __ssx_critical_stack; + +/// This is the stack pointer saved when switching from a thread context to a +/// full-mode non-critical interrupt context. + +UNLESS__SSX_CORE_C__(extern) +volatile +SsxAddress __ssx_saved_sp_noncritical; + +/// The non-critical interrupt stack; constant once defined by the call of +/// ssx_initialize(). + +UNLESS__SSX_CORE_C__(extern) +volatile +SsxAddress __ssx_noncritical_stack; + +/// This is the run queue - the queue of mapped runnable tasks. +UNLESS__SSX_CORE_C__(extern) +volatile +SsxThreadQueue __ssx_run_queue; + +/// This flag is set by \c __ssx_schedule() if a new highest-priority thread +/// becomes runnable during an interrupt handler. The context switch will +/// take place at the end of non-critical interrupt processing, and the +/// interrupt handling code will clear the flag. + +UNLESS__SSX_CORE_C__(extern) +volatile +int __ssx_delayed_switch; + +/// The currently running thread, or NULL (0) to indicate the idle thread +/// +/// \a __ssx_current_thread holds a pointer to the currently executing +/// thread. This pointer will be NULL (0) under the following conditions: +/// +/// - After ssx_initialize() but prior to ssx_start_threads() +/// +/// - After ssx_start_threads(), when no threads are runnable. In this case +/// the NULL (0) value indicates that the SSX idle thread is 'running'. +/// +/// - After ssx_start_threads(), when the current (non-idle) thread has +/// completed or been deleted. +/// +/// If \a __ssx_current_thread == 0 then there is no requirement to save any +/// register state on a context switch, either because the SSX idle thread has +/// no permanent context, or because any thread context on the kernel stack is +/// associated with a deleted thread. +/// +/// If \a __ssx_current_thread != 0 then \a __ssx_current_thread is a pointer +/// to the currently executing thread. In an interrupt handler \a +/// ssx_current_thread is a pointer to the thread whose context is saved on +/// the kernel stack. +UNLESS__SSX_CORE_C__(extern) +volatile +SsxThread* __ssx_current_thread; + +/// The thread to switch to during the next context switch, or NULL (0). +/// +/// \a __ssx_next_thread is computed by __ssx_schedule(). \a +/// __ssx_next_thread holds a pointer to the thread to switch to at the next +/// context switch. In a thread context the switch happens immediately if \a +/// __ssx_next_thread == 0 or \a __ssx_next_thread != \a __ssx_current_thread. +/// In an interrupt context the check happens at the end of processing all +/// SSX_NONCRITICAL interrupts. +/// +/// \a __ssx_next_thread may be NULL (0) under the following +/// conditions: +/// +/// - After ssx_initialize() but prior to ssx_start_threads(), assuming no +/// threads have been made runnable. +/// +/// - After ssx_start_threads(), when no threads are runnable. In this case +/// the NULL (0) value indicates that the SSX idle thread is the next thread +/// to 'run'. +/// +/// If \a __ssx_next_thread == 0 then there is no requirement to restore +/// any register state on a context switch, because the SSX idle thread has +/// no permanent context. +/// +/// If \a __ssx_next_thread != 0 then \a __ssx_next_thread is a pointer +/// to the thread whose context will be restored at the next context switch. +UNLESS__SSX_CORE_C__(extern) +volatile +SsxThread* __ssx_next_thread; + +/// The priority of \a __ssx_next_thread +/// +/// If \a __ssx_next_thread == 0, the \a __ssx_next_priority == SSX_THREADS. +UNLESS__SSX_CORE_C__(extern) +volatile +SsxThreadPriority __ssx_next_priority; + +/// This variable holds the default thread machine context for newly created +/// threads. The idle thread also uses this context. This variable is normally +/// constant after the call of \c ssx_initialize(). + +UNLESS__SSX_CORE_C__(extern) +volatile +SsxMachineContext __ssx_thread_machine_context_default; + + +/// The size of the noncritical stack (bytes). + +UNLESS__SSX_CORE_C__(extern) +volatile +size_t __ssx_noncritical_stack_size; + +/// The size of the critical stack (bytes). + +UNLESS__SSX_CORE_C__(extern) +volatile +size_t __ssx_critical_stack_size; + +/// This table maps priorities to threads, and contains SSX_THREADS + 1 +/// entries. The final entry is for the idle thread and will always be null +/// after initizlization. + +UNLESS__SSX_CORE_C__(extern) +volatile +SsxThread* __ssx_priority_map[SSX_THREADS + 1]; + +/// The SSX time queue structure +/// +/// This structure is defined for use by the kernel, however applications +/// could also use this structure to define their own time queues. + +typedef struct { + + /// A sentinel node for the time queue. + /// + /// The time queue is an SsxDeque managed as a FIFO queue for queue + /// management purpose, although events time out in time order. + /// + /// This pointer container is defined as the first element of the + /// structure to allow the SsxTimeQueue to be cast to an SsxDeque. + SsxDeque queue; + + /// The next timeout in absolute time. + SsxTimebase next_timeout; + + /// A pointer to allow preemption of time queue processing + /// + /// If non-0, then this is the next timer in the time queue to handle, or + /// a pointer to the \a queue object indicating no more timers to handle. + /// + /// \a cursor != 0 implies that time queue handler is in the midst of + /// processing the time queue, but has enabled interrupt preemption for + /// processing a timer handler. This means that 1) if the timer pointed to + /// by \a cursor is deleted then the cursor must be assigned to the + /// next timer in the queue; and 2) if a new timer is scheduled then + /// activating the next timeout will be handled by the timer handler. + SsxDeque* cursor; + +} SsxTimeQueue; + +UNLESS__SSX_CORE_C__(extern) +SsxTimeQueue __ssx_time_queue; + +/// Return a pointer to the SsxThread object of the currently running thread, +/// or NULL (0) if SSX is idle or has not been started. +/// +/// In this API the current thread is not volatile - it will never change +/// inside application code - thus the 'volatile' is cast away. The SSX kernel +/// does not (must not) use this API. + +UNLESS__SSX_CORE_C__(extern) +inline SsxThread * +ssx_current(void) +{ + return (SsxThread *)__ssx_current_thread; +} + + +/// Set the timebase. This is only called at initialization. Machine +/// specific. + +void +__ssx_timebase_set(SsxTimebase t); + +/// Schedule the next timeout in a machine-specific way. + +void +__ssx_schedule_hardware_timeout(SsxTimebase timeout); + +/// Cancel the next timeout in a machine-specific way. + +void +__ssx_cancel_hardware_timeout(void); + +/// The thread timeout handler. Portable. + +SSX_TIMER_CALLBACK(__ssx_thread_timeout); + +/// Generic stack initialization. Portable. + +int +__ssx_stack_init(SsxAddress *stack, + size_t *size); + +/// Machine-specific thread context initialization. + +void +__ssx_thread_context_initialize(SsxThread *thread, + SsxThreadRoutine thread_routine, + void *arg); + +/// Machine specific resumption of __ssx_next_thread at __ssx_next_priority +/// without saving the current context. +void +__ssx_next_thread_resume(void); + +/// Schedule a timer in the time queue. Portable. +void +__ssx_timer_schedule(SsxTimer *timer); + +/// Remove a timer from the time queue. Portable. +int +__ssx_timer_cancel(SsxTimer *timer); + +void +__ssx_schedule(void); + + +// Call the application main(). Portable. + +void +__ssx_main(int argc, char **argv); + +#endif /* __ASSEMBLER__ */ + +#endif /* __SSX_KERNEL_H__ */ diff --git a/src/ssx/ssx/ssx_macros.h b/src/ssx/ssx/ssx_macros.h new file mode 100755 index 0000000..76d3ba7 --- /dev/null +++ b/src/ssx/ssx/ssx_macros.h @@ -0,0 +1,119 @@ +#ifndef __SSX_MACROS_H__ +#define __SSX_MACROS_H__ + +// $Id: ssx_macros.h,v 1.2 2014/02/03 01:30:44 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_macros.h,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_macros.h +/// \brief Boilerplate macros for SSX + +/// This macro encapsulates error handling boilerplate for code that uses the +/// SSX API-type error handling, for errors that do not occur in critical +/// sections. + +#define SSX_ERROR(code) \ + do { \ + if (SSX_ERROR_PANIC) { \ + SSX_PANIC(code); \ + } else { \ + return -(code); \ + } \ + } while (0) + + +/// This macro encapsulates error handling boilerplate in the SSX API +/// functions, for errors that do not occur in critical sections. + +#define SSX_ERROR_IF(condition, code) \ + do { \ + if (condition) { \ + SSX_ERROR(code); \ + } \ + } while (0) + + +/// This macro encapsulates error handling boilerplate in the SSX API +/// functions, for errors that do not occur in critical sections and always +/// force a kernel panic, indicating a kernel or API bug. + +#define SSX_PANIC_IF(condition, code) \ + do { \ + if (condition) { \ + SSX_PANIC(code); \ + } \ + } while (0) + + +/// This macro encapsulates error handling boilerplate in the SSX API +/// functions, for errors that do not occur in critical sections. +/// The error handling will only be enabled when SSX_ERROR_CHECK_API +/// is enabled. + +#define SSX_ERROR_IF_CHECK_API(condition, code) \ + do { \ + if (SSX_ERROR_CHECK_API) { \ + SSX_ERROR_IF(condition, code); \ + } \ + } while (0) + +/// This macro encapsulates error handling boilerplate in the SSX API +/// functions, for errors that occur in critical sections. + +#define SSX_ERROR_IF_CRITICAL(condition, code, context) \ + do { \ + if (condition) { \ + if (SSX_ERROR_PANIC) { \ + SSX_PANIC(code); \ + ssx_critical_section_exit(context); \ + } else { \ + ssx_critical_section_exit(context); \ + return -(code); \ + } \ + } \ + } while (0) + + +/// This is a general macro for errors that require cleanup before returning +/// the error code. + +#define SSX_ERROR_IF_CLEANUP(condition, code, cleanup) \ + do { \ + if (condition) { \ + if (SSX_ERROR_PANIC) { \ + SSX_PANIC(code); \ + cleanup; \ + } else { \ + cleanup; \ + return -(code); \ + } \ + } \ + } while (0) + + +/// Most SSX APIs can not be called from critical interrupt contexts. + +#define SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT() \ + SSX_ERROR_IF(__ssx_kernel_context_critical_interrupt(), \ + SSX_ILLEGAL_CONTEXT_CRITICAL_INTERRUPT) + + +/// Some SSX APIs can only be called from thread contexts - these are APIs +/// that threads call on 'themselves'. + +#define SSX_ERROR_UNLESS_THREAD_CONTEXT() \ + SSX_ERROR_IF(!__ssx_kernel_context_thread(), \ + SSX_ILLEGAL_CONTEXT_THREAD_CONTEXT) + + +/// Some SSX APIs must be called from an interrupt context only. + +#define SSX_ERROR_UNLESS_ANY_INTERRUPT_CONTEXT() \ + SSX_ERROR_IF(!__ssx_kernel_context_any_interrupt(), \ + SSX_ILLEGAL_CONTEXT_INTERRUPT_CONTEXT) + +#endif /* __SSX_MACROS_H__ */ diff --git a/src/ssx/ssx/ssx_semaphore_core.c b/src/ssx/ssx/ssx_semaphore_core.c new file mode 100755 index 0000000..f1f64e8 --- /dev/null +++ b/src/ssx/ssx/ssx_semaphore_core.c @@ -0,0 +1,331 @@ +// $Id: ssx_semaphore_core.c,v 1.2 2014/02/03 01:30:44 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_semaphore_core.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_semaphore_core.c +/// \brief SSX semaphore APIs +/// +/// The entry points in this file are considered 'core' routines that will +/// always be present at runtime in any SSX application that enables +/// semaphores. + +#include "ssx.h" + +/// Post a count to a semaphore +/// +/// \param semaphore A pointer to the semaphore +/// +/// If any thread is pending on the semaphore, the highest priority thread +/// will be made runnable and the internal count will remain 0. +/// +/// If no thread is pending on the semaphore then the internal count will be +/// incremented by 1, with overflow wrapping the internal count through 0. If +/// the \a max_count argument supplied when the semaphore was created is +/// non-zero and the new internal count is greater than the \a max_count, an +/// overflow error will be signalled. +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_ILLEGAL_CONTEXT The API was called from a critical interrupt +/// context. +/// +/// \retval -SSX_INVALID_SEMAPHORE_AT_POST The \a semaphore is a null (0) pointer. +/// +/// \retval -SSX_SEMAPHORE_OVERFLOW The \a max_count argument supplied when +/// the semaphore was created is non-zero and the new internal count is +/// greater than the \a max_count. + +int +ssx_semaphore_post(SsxSemaphore *semaphore) +{ + SsxMachineContext ctx; + SsxThreadPriority priority; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); + SSX_ERROR_IF(semaphore == 0, SSX_INVALID_SEMAPHORE_AT_POST); + } + + ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); + + priority = __ssx_thread_queue_min(&(semaphore->pending_threads)); + + if (priority != SSX_IDLE_THREAD_PRIORITY) { + + __ssx_thread_queue_delete(&(semaphore->pending_threads), priority); + __ssx_thread_queue_insert(&__ssx_run_queue, priority); + + SSX_TRACE_THREAD_SEMAPHORE_POST(priority); + + __ssx_schedule(); + + } else { + + semaphore->count++; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((semaphore->max_count > 0) && + (semaphore->count > semaphore->max_count), + SSX_SEMAPHORE_OVERFLOW); + } + } + + ssx_critical_section_exit(&ctx); + + return SSX_OK; +} + + +/// Pend on a semaphore with timeout +/// +/// \param semaphore A pointer to the semaphore +/// +/// \param timeout A relative timeout in SSX timebase ticks, including the +/// special values SSX_NO_WAIT and SSX_WAIT_FOREVER +/// +/// This API is normally called from threads, and can only be successfully +/// called from interupt handlers under special conditions. +/// +/// If the internal count of the \a semaphore is non-zero, the internal count +/// is decremented by one and execution of the caller continues. +/// +/// If the internal count of the \a semaphore is zero and the \a timeout is +/// SSX_NO_WAIT (0) then the call returns immediately with the informational +/// code -SSX_SEMAPHORE_PEND_NO_WAIT. +/// +/// If the internal count of the \a semaphore is zero and the \a timeout is +/// non-zero then a thread will block until either a semaphore count is +/// acquired or the relative timeout expires. If this condition occurs in a +/// call from an interrupt context or before threads have been started then +/// the call will fail with the error \c -SSX_SEMAPHORE_PEND_WOULD_BLOCK. +/// +/// Once timed out the thread is removed from the semaphore pending queue and +/// made runnable, and the ssx_semaphore_pend() operation will fail, even if +/// the semaphore count becomes available before the thread runs again. The +/// ssx_semaphore_pend() API returns the informational code +/// -SSX_SEMAPHORE_PEND_TIMED_OUT in this case. +/// +/// By convention, a timeout interval equal to the maximum possible value of +/// the \c SsxInterval type is taken to mean "wait forever". A thread blocked +/// on a semaphore in this mode will never time out. SSX provides this +/// constant as \c SSX_WAIT_FOREVER. +/// +/// Return values other than SSX_OK (0) are not necessarily errors; see \ref +/// ssx_errors +/// +/// The following return codes are non-error codes: +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_SEMAPHORE_PEND_NO_WAIT timeout is set to SSX_NO_WAIT +/// +/// \retval -SSX_SEMAPHORE_PEND_TIMED_OUT The semaphore was not acquired +/// before the timeout expired. +/// +/// The following return codes are error codes: +/// +/// \retval -SSX_ILLEGAL_CONTEXT The API was called from a critical interrupt +/// context. +/// +/// \retval -SSX_INVALID_SEMAPHORE_AT_PEND The \a semaphore is a null (0) +/// pointer. +/// +/// \retval -SSX_SEMAPHORE_PEND_WOULD_BLOCK The call was made from an +/// interrupt context (or before threads have been started), the semaphore +/// internal count was 0 and a non-zero timeout was specified. + +// Note: Casting __ssx_current_thread removes the 'volatile' attribute. + +int +ssx_semaphore_pend(SsxSemaphore *semaphore, + SsxInterval timeout) +{ + SsxMachineContext ctx; + SsxThreadPriority priority; + SsxThread *thread; + SsxTimer *timer = 0; + int rc = SSX_OK; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); + SSX_ERROR_IF(semaphore == 0, SSX_INVALID_SEMAPHORE_AT_PEND); + } + + ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); + + if (semaphore->count != 0) { + + semaphore->count--; + + } else if (timeout == SSX_NO_WAIT) { + + rc = -SSX_SEMAPHORE_PEND_NO_WAIT; + + } else { + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF_CRITICAL(!__ssx_kernel_context_thread(), + SSX_SEMAPHORE_PEND_WOULD_BLOCK, + &ctx); + } + + thread = (SsxThread *)__ssx_current_thread; + priority = thread->priority; + + __ssx_thread_queue_insert(&(semaphore->pending_threads), priority); + + thread->semaphore = semaphore; + thread->flags |= SSX_THREAD_FLAG_SEMAPHORE_PEND; + + SSX_TRACE_THREAD_SEMAPHORE_PEND(priority); + + if (timeout != SSX_WAIT_FOREVER) { + timer = &(thread->timer); + timer->timeout = ssx_timebase_get() + timeout; + __ssx_timer_schedule(timer); + thread->flags |= SSX_THREAD_FLAG_TIMER_PEND; + } + + __ssx_thread_queue_delete(&__ssx_run_queue, priority); + __ssx_schedule(); + + thread->flags &= ~SSX_THREAD_FLAG_SEMAPHORE_PEND; + + if (thread->flags & SSX_THREAD_FLAG_TIMER_PEND) { + if (thread->flags & SSX_THREAD_FLAG_TIMED_OUT) { + rc = -SSX_SEMAPHORE_PEND_TIMED_OUT; + } else { + __ssx_timer_cancel(timer); + } + thread->flags &= + ~(SSX_THREAD_FLAG_TIMER_PEND | SSX_THREAD_FLAG_TIMED_OUT); + } + } + + ssx_critical_section_exit(&ctx); + + return rc; +} + + +/// Release all threads blocked on a semaphore +/// +/// \param semaphore A pointer to a semaphore +/// +/// This API is provided to allow an SSX semaphore to be used as a thread +/// barrier. ssx_semaphore_release_all() simultaneously unblocks all threads +/// (if any) currently pending on a semaphore. A semaphore to be used as a +/// thread barrier will typically be initialized with +/// ssx_semaphore_create(\a sem, 0, 0), and sxx_semaphore_post() would never be +/// called on the \a sem. +/// +/// This API never modifies the \a count field of the semaphore; If any +/// threads are blocked on a semaphore the semaphore count is 0 by definition. +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_ILLEGAL_CONTEXT The API was called from a critical interrupt +/// context. +/// +/// \retval -SSX_INVALID_SEMAPHORE_AT_RELEASE The \a semaphore is a null (0) +/// pointer. + +int +ssx_semaphore_release_all(SsxSemaphore* semaphore) +{ + SsxMachineContext ctx; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); + SSX_ERROR_IF(semaphore == 0, SSX_INVALID_SEMAPHORE_AT_RELEASE); + } + + ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); + + __ssx_thread_queue_union(&__ssx_run_queue, &(semaphore->pending_threads)); + __ssx_thread_queue_clear(&(semaphore->pending_threads)); + __ssx_schedule(); + + ssx_critical_section_exit(&ctx); + + return SSX_OK; +} + + +/// Get information about a semaphore. +/// +/// \param semaphore A pointer to the SsxSemaphore to query +/// +/// \param count The value returned through this pointer is the current count +/// of the semaphore. The caller can set this parameter to the null pointer +/// (0) if this information is not required. +/// +/// \param pending The value returned through this pointer is the current +/// number of threads pending on the semaphore. The caller can set this +/// parameter to the null pointer (0) if this information is not required. +/// +/// The information returned by this API can only be guaranteed consistent if +/// the API is called from an SSX_NONCRITICAL critical section. Since the +/// implementation of this API does not require a critical section, it is not +/// an error to call this API from a critical interrupt context. +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_SEMAPHORE_AT_INFO The \a semaphore is a null (0) +/// pointer. + +int +ssx_semaphore_info_get(SsxSemaphore* semaphore, + SsxSemaphoreCount* count, + int* pending) + +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(semaphore == 0, SSX_INVALID_SEMAPHORE_AT_INFO); + } + + if (count) { + *count = semaphore->count; + } + if (pending) { + *pending = __ssx_thread_queue_count(&(semaphore->pending_threads)); + } + + return SSX_OK; +} + + +/// An simple interrupt handler that posts to a semaphore. +/// +/// To implement basic event-driven blocking of a thread, install +/// ssx_semaphore_post_handler() as the handler for a non-critical interrupt +/// and provide a pointer to the semaphore as the \a arg argument in +/// ssx_irq_handler_set(). The semaphore should be initialized with +/// ssx_semaphore_create(&sem, 0, 1). This handler simply disables (masks) +/// the interrupt, clears the status and calls ssx_semaphore_post() on the +/// semaphore. +/// +/// Note that clearing the status in the interrupt controller as done here is +/// effectively a no-op for level-sensitive interrupts. In the level-sensitive +/// case any thread pending on the semaphore must reset the interrupt +/// condition in the device before re-enabling the interrupt. + +void +ssx_semaphore_post_handler_full(void *arg, SsxIrqId irq, int priority) +{ + ssx_irq_disable(irq); + ssx_irq_status_clear(irq); + ssx_semaphore_post((SsxSemaphore *)arg); +} + +SSX_IRQ_FAST2FULL(ssx_semaphore_post_handler, ssx_semaphore_post_handler_full); diff --git a/src/ssx/ssx/ssx_semaphore_init.c b/src/ssx/ssx/ssx_semaphore_init.c new file mode 100755 index 0000000..98bba89 --- /dev/null +++ b/src/ssx/ssx/ssx_semaphore_init.c @@ -0,0 +1,84 @@ +// $Id: ssx_semaphore_init.c,v 1.2 2014/02/03 01:30:44 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_semaphore_init.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_semaphore_init.c +/// \brief SSX semaphore API initialization routines +/// +/// The entry points in this file are routines that are typically used during +/// initialization, and their code space could be deallocated and recovered if +/// no longer needed by the application after initialization. + +#include "ssx.h" + +/// Create (initialize) a semaphore +/// +/// \param semaphore A pointer to an SsxSemaphore structure to initialize +/// +/// \param initial_count The initial count of the semaphore +/// +/// \param max_count The maximum count allowed in the semaphore, for error +/// checking +/// +/// Semaphores are created (initialized) by a call of \c +/// ssx_semaphore_create(), using an application-provided instance of an \c +/// SsxSemaphore structure. This structure \e is the semaphore, so the +/// application must never modify the structure if the semaphore is in use. +/// SSX has no way to know if an \c SsxSemaphore structure provided to +/// \c ssx_semaphore_create() is safe to use as a semaphore, and will silently +/// modify whatever memory is provided. +/// +/// SSX provides two simple overflow semantics based on the value of max_count +/// in the call of \c ssx_semaphore_create(). +/// +/// If \a max_count = 0, then posting to the semaphore first increments the +/// internal count by 1. Overflows are ignored and will wrap the internal +/// count through 0. +/// +/// If \a max_count != 0, then posting to the semaphore first increments the +/// internal count by 1, wrapping through 0 in the event of overflow. If the +/// resulting count is greater than max_count, \c ssx_semaphore_post() will +/// return the error \c -SSX_SEMAPHORE_POST_OVERFLOW to the caller. +/// +/// In most applications it is probably best to use the \a max_count != 0 +/// semantics to trap programming errors, unless there is a specific +/// application where overflow is expected and ignorable. As a fine point of +/// the specification, a \a max_count of 0 is equivalent to a max_count of +/// 0xFFFFFFFF. +/// +/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_SEMAPHORE_AT_CREATE The \a semaphore is a null (0) +/// pointer. +/// +/// \retval -SSX_INVALID_ARGUMENT_SEMAPHORE The \a max_count is non-zero +/// and less than the \a initial_count. + +int +ssx_semaphore_create(SsxSemaphore *semaphore, + SsxSemaphoreCount initial_count, + SsxSemaphoreCount max_count) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(semaphore == 0, SSX_INVALID_SEMAPHORE_AT_CREATE); + SSX_ERROR_IF((max_count != 0) && (initial_count > max_count), + SSX_INVALID_ARGUMENT_SEMAPHORE); + } + + __ssx_thread_queue_clear(&(semaphore->pending_threads)); + semaphore->count = initial_count; + semaphore->max_count = max_count; + + return SSX_OK; +} + + + + + diff --git a/src/ssx/ssx/ssx_stack_init.c b/src/ssx/ssx/ssx_stack_init.c new file mode 100755 index 0000000..9d6331a --- /dev/null +++ b/src/ssx/ssx/ssx_stack_init.c @@ -0,0 +1,87 @@ +// $Id: ssx_stack_init.c,v 1.1.1.1 2013/12/11 21:03:28 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_stack_init.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_stack_init.c +/// \brief SSX stack initialization +/// +/// The entry points in this file are initialization routines - they are never +/// needed after SSX initialization and their code space could be reclaimed by +/// the application after initialization if required. +/// +/// This code was split out from "ssx_init.c" because it may be needed in a +/// thread configuration if threads are being created dynamically. in an +/// interrupt-only configuration it is not needed after \c ssx_initialize(). + +#include "ssx.h" + +/// Initialize a stack area. +/// +/// \param stack A pointer to the smallest legal address of the stack. The +/// stack address is modified as the stack is aligned and initialized. +/// +/// \param size A pointer to the size of the stack (in bytes). The size is +/// modified as the stack is aligned and initialized. At exit this is the +/// final usable stack area size aligned to the size of the SSX_STACK_TYPE. +/// +/// SSX makes no assumptions about size or alignment of the area provided as a +/// stack, and carefully aligns and initializes the stack. Regardless of how +/// the stack grows, the \a stack parameter is considered to be the lowest +/// legal address of the stack. + +int +__ssx_stack_init(SsxAddress *stack, + size_t *size) +{ + SsxAddress mask; + size_t excess, i, count; + SSX_STACK_TYPE *p; + + if (SSX_STACK_DIRECTION < 0) { + + // Stacks grow down. The initial stack pointer is set to just above + // the last allocated stack address. This is legal for pre-decrement + // stacks, otherwise the initial address is first brought into range + // before alignment. The stack is aligned downward, then the size is + // adjusted to a multiple of the stack type. Stacks are optionally + // prepatterned. Alignment is assumed to be a power of 2. + + *stack += *size; + + if (!SSX_STACK_PRE_DECREMENT) { + *stack -= sizeof(SSX_STACK_TYPE); + *size -= sizeof(SSX_STACK_TYPE); + } + + mask = SSX_STACK_ALIGNMENT - 1; + excess = *stack & mask; + *stack -= excess; + *size -= excess; + *size = (*size / sizeof(SSX_STACK_TYPE)) * sizeof(SSX_STACK_TYPE); + + if (SSX_STACK_CHECK) { + p = (SSX_STACK_TYPE *)(*stack); + count = *size / sizeof(SSX_STACK_TYPE); + for (i = 0; i < count; i++) { + if (SSX_STACK_PRE_DECREMENT) { + *(--p) = SSX_STACK_PATTERN; + } else { + *(p--) = SSX_STACK_PATTERN; + } + } + } + + __ssx_stack_create_initial_frame(stack, size); + + } else { + + SSX_PANIC(SSX_UNIMPLEMENTED); + } + + return SSX_OK; +} + diff --git a/src/ssx/ssx/ssx_thread_core.c b/src/ssx/ssx/ssx_thread_core.c new file mode 100755 index 0000000..d6124e8 --- /dev/null +++ b/src/ssx/ssx/ssx_thread_core.c @@ -0,0 +1,946 @@ +// $Id: ssx_thread_core.c,v 1.2 2014/02/03 01:30:44 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_thread_core.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_thread_core.c +/// \brief SSX thread APIs +/// +/// The entry points in this file are considered 'core' routines that will +/// always be present at runtime in any SSX application that enables threads. + +#include "ssx.h" + +#define __SSX_THREAD_CORE_C__ + + +// This routine is only used locally. Noncritical interrupts must be disabled +// at entry. + +static inline int +__ssx_thread_is_active(SsxThread *thread) +{ + return ((thread->state != SSX_THREAD_STATE_COMPLETED) && + (thread->state != SSX_THREAD_STATE_DELETED)); +} + + +// This routine is only used locally. Noncritical interrupts must be disabled +// at entry. + +static inline int +__ssx_thread_is_mapped(SsxThread *thread) +{ + return (thread->state == SSX_THREAD_STATE_MAPPED); +} + + +// This routine is only used locally. Noncritical interrupts must be disabled +// at entry. This is only called on mapped threads. + +static inline int +__ssx_thread_is_runnable(SsxThread *thread) +{ + return __ssx_thread_queue_member(&__ssx_run_queue, thread->priority); +} + + +// This routine is only used locally. Noncritical interrupts must be disabled +// at entry. + +static inline SsxThread* +__ssx_thread_at_priority(SsxThreadPriority priority) +{ + return (SsxThread*)__ssx_priority_map[priority]; +} + + +// This routine is only used locally. Noncritical interrupts must be disabled +// at entry. The caller must also have checked that the priority is free. +// This routine is only called on threads known to be in a suspended state, +// either SSX_THREAD_STATE_SUSPENDED_RUNNABLE or +// SSX_THREAD_STATE_SUSPENDED_BLOCKED. Mapping a runnable thread adds it to +// the run queue. Mapping a thread pending on a semaphore either takes the +// count and becomes runnable or adds the thread to the pending queue for the +// semaphore. Mapping a sleeping thread requires no further action +// here. Scheduling after the map must be handled by the caller. + +void +__ssx_thread_map(SsxThread* thread) +{ + SsxThreadPriority priority; + + priority = thread->priority; + __ssx_priority_map[priority] = thread; + + if (thread->state == SSX_THREAD_STATE_SUSPENDED_RUNNABLE) { + + __ssx_thread_queue_insert(&__ssx_run_queue, priority); + + } else if (thread->flags & SSX_THREAD_FLAG_SEMAPHORE_PEND) { + + if (thread->semaphore->count) { + + thread->semaphore->count--; + __ssx_thread_queue_insert(&__ssx_run_queue, priority); + + } else { + + __ssx_thread_queue_insert(&(thread->semaphore->pending_threads), + priority); + } + } + + thread->state = SSX_THREAD_STATE_MAPPED; + + if (SSX_KERNEL_TRACE_ENABLE) { + if (__ssx_thread_is_runnable(thread)) { + SSX_TRACE_THREAD_MAPPED_RUNNABLE(priority); + } else if (thread->flags & SSX_THREAD_FLAG_SEMAPHORE_PEND) { + SSX_TRACE_THREAD_MAPPED_SEMAPHORE_PEND(priority); + } else { + SSX_TRACE_THREAD_MAPPED_SLEEPING(priority); + } + } +} + + +// This routine is only used locally. Noncritical interrupts must be disabled +// at entry. This routine is only ever called on threads in the +// SSX_THREAD_STATE_MAPPED. Unmapping a thread removes it from the priority +// map, the run queue and any semaphore pend, but does not cancel any +// timers. Scheduling must be handled by the code calling +// __ssx_thread_unmap(). + +void +__ssx_thread_unmap(SsxThread *thread) +{ + SsxThreadPriority priority; + + priority = thread->priority; + __ssx_priority_map[priority] = 0; + + if (__ssx_thread_is_runnable(thread)) { + + thread->state = SSX_THREAD_STATE_SUSPENDED_RUNNABLE; + __ssx_thread_queue_delete(&__ssx_run_queue, priority); + + } else { + + thread->state = SSX_THREAD_STATE_SUSPENDED_BLOCKED; + if (thread->flags & SSX_THREAD_FLAG_SEMAPHORE_PEND) { + __ssx_thread_queue_delete(&(thread->semaphore->pending_threads), + priority); + } + } +} + + +// Schedule and run the highest-priority mapped runnable thread. +// +// The priority of the next thread to run is first computed. This may be +// SSX_THREADS, indicating that the only thread to run is the idle thread. +// This will always cause (or defer) a 'context switch' to the idle thread. +// Otherwise, if the new thread is not equal to the current thread this will +// also cause (or defer) a context switch. Note that scheduling is defined in +// terms of priorities but actually implemented in terms of SsxThread pointers. +// +// If we are not yet in thread mode we're done - threads will be started by +// ssx_start_threads() later. If we're in thread context a context switch +// happens immediately. In an interrupt context the switch is deferred to the +// end of SSX_NONCRITICAL interrupt processing. + +void +__ssx_schedule(void) +{ + __ssx_next_priority = __ssx_thread_queue_min(&__ssx_run_queue); + __ssx_next_thread = __ssx_priority_map[__ssx_next_priority]; + + if ((__ssx_next_thread == 0) || + (__ssx_next_thread != __ssx_current_thread)) { + + if (__ssx_kernel_mode_thread()) { + if (__ssx_kernel_context_thread()) { + if (__ssx_current_thread != 0) { + __ssx_switch(); + } else { + __ssx_next_thread_resume(); + } + } else { + __ssx_delayed_switch = 1; + } + } + } +} + + +// This routine is only used locally. +// +// Completion and deletion are pretty much the same thing. Completion is +// simply self-deletion of the current thread (which is mapped by +// definition.) The complete/delete APIs have slightly different error +// conditions but are otherwise the same. +// +// Deleting a mapped thread first unmaps (suspends) the thread, which takes +// care of removing the thread from any semaphores it may be pending on. Then +// any outstanding timer is also cancelled. +// +// If the current thread is being deleted we install the idle thread as +// __ssx_current_thread, so scheduling is forced and no context is saved on +// the context switch. +// +// Note that we do not create trace events for unmapped threads since the trace +// tag only encodes the priority, which may be in use by a mapped thread. + +void +__ssx_thread_delete(SsxThread *thread, SsxThreadState final_state) +{ + SsxMachineContext ctx; + int mapped; + + ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); + + mapped = __ssx_thread_is_mapped(thread); + + if (mapped) { + __ssx_thread_unmap(thread); + } + + __ssx_timer_cancel(&(thread->timer)); + thread->state = final_state; + + if (mapped) { + + if (SSX_KERNEL_TRACE_ENABLE) { + if (final_state == SSX_THREAD_STATE_DELETED) { + SSX_TRACE_THREAD_DELETED(thread->priority); + } else { + SSX_TRACE_THREAD_COMPLETED(thread->priority); + } + } + + if (thread == __ssx_current_thread) { + __ssx_current_thread = 0; + } + __ssx_schedule(); + } + + ssx_critical_section_exit(&ctx); +} + + +// Generic thread timeout +// +// This routine is called as a timer callback either because a sleeping thread +// has timed out or a thread pending on a semaphore has timed out. If the +// thread is not already runnable then the the timeout flag is set, and if the +// thread is mapped it is scheduled. +// +// This implementation allows that a thread blocked on a timer may have been +// made runnable by some other mechanism, such as acquiring a semaphore. In +// order to provide an iteration-free implementation of +// ssx_semaphore_release_all(), cancelling any semaphore timeouts is deferred +// until the thread runs again. +// +// __ssx_thread_timeout() is currenly the only timer interrupt called from a +// critical section. +// +// Note that we do not create trace events for unmapped threads since the trace +// tag only encodes the priority, which may be in use by a mapped thread. + +void +__ssx_thread_timeout(void *arg) +{ + SsxThread *thread = (SsxThread *)arg; + + switch (thread->state) { + + case SSX_THREAD_STATE_MAPPED: + if (!__ssx_thread_is_runnable(thread)) { + thread->flags |= SSX_THREAD_FLAG_TIMED_OUT; + __ssx_thread_queue_insert(&__ssx_run_queue, thread->priority); + __ssx_schedule(); + } + break; + + case SSX_THREAD_STATE_SUSPENDED_RUNNABLE: + break; + + case SSX_THREAD_STATE_SUSPENDED_BLOCKED: + thread->flags |= SSX_THREAD_FLAG_TIMED_OUT; + thread->state = SSX_THREAD_STATE_SUSPENDED_RUNNABLE; + break; + + default: + SSX_PANIC(SSX_THREAD_TIMEOUT_STATE); + } +} + + +// This routine serves as a container for the SSX_START_THREADS_HOOK and +// actually starts threads. The helper routine __ssx_call_ssx_start_threads() +// arranges this routine to be called with interrupts disabled while running +// on the noncritical interrupt stack. +// +// The reason for this roundabout is that we want to be able to run a hook +// routine (transparent to the application) that can hand over every last byte +// of free memory to "malloc()" - including the stack of main(). Since we +// always need to run on some stack, we chose to run the hook on the kernel +// noncritical interrupt stack. However to do this safely we need to make sure +// that no interrupts will happen during this time. When __ssx_thread_resume() +// is finally called all stack-based context is lost but it doesn't matter at +// that point - it's a one-way street into thread execution. +// +// This is considered part of ssx_start_threads() and so is also considered a +// 'core' routine. + +void +__ssx_start_threads(void) +{ + SSX_START_THREADS_HOOK; + + __ssx_next_thread_resume(); + + SSX_PANIC(SSX_START_THREADS_RETURNED); +} + + +/// Start SSX threads +/// +/// This routine starts the SSX thread scheduler infrastructure. This routine +/// must be called after a call of \c ssx_initialize(). This routine never +/// returns. Interrupt (+ timer) only configurations of SSX need not call this +/// routine. +/// +/// Note: This tiny routine is considered a 'core' routine so that the +/// initialziation code can safely recover all 'init' code space before +/// starting threads. +/// +/// This routine typically does not return - any return value indicates an +/// error; see \ref ssx_errors +/// +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was called twice. + +int +ssx_start_threads(void) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(__ssx_kernel_mode_thread(), SSX_ILLEGAL_CONTEXT_THREAD); + } + + __ssx_call_ssx_start_threads(); + + return 0; +} + + +/// Resume a suspended thread +/// +/// \param thread The thread to resume +/// +/// SSX only allows one thread at a time to run at a given priority, and +/// implements the notion of a thread \e claiming a priority. A suspended +/// thread claims a priority when it is mapped by a call of +/// ssx_thread_resume(). This API will succeed only if no other active thread +/// is currently mapped at the priority assigned to the thread. SSX provides +/// the ssx_thread_at_priority() API which allows an application-level +/// scheduler to correctly manage multiple threads running at the same +/// priority. +/// +/// If the thread was sleeping while suspended it remains asleep. However if +/// the sleep timer timed out while the thread was suspended it will be +/// resumed runnable. +/// +/// If the thread was blocked on a semaphore when it was suspended, then when +/// the thread is resumed it will attempt to reacquire the semaphore. +/// However, if the thread was blocked on a semaphore with timeout while +/// suspended and the timeout interval has passed, the thread will be resumed +/// runnable and see that the semaphore pend timed out. +/// +/// It is not an error to call ssx_thread_resume() on a mapped +/// thread. However it is an error to call ssx_thread_resume() on a completed +/// or deleted thread. +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion, including calls on a \a thread that is +/// already mapped. +/// +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was called +/// from a critical interrupt context. +/// +/// \retval -SSX_INVALID_THREAD_AT_RESUME1 The \a thread is a null (0) pointer. +/// +/// \retval -SSX_INVALID_THREAD_AT_RESUME2 The \a thread is not active, +/// i.e. has completed or been deleted. +/// +/// \retval -SSX_PRIORITY_IN_USE_AT_RESUME Another thread is already mapped at +/// the priority of the \a thread. + +int +ssx_thread_resume(SsxThread *thread) +{ + SsxMachineContext ctx; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); + SSX_ERROR_IF(thread == 0, SSX_INVALID_THREAD_AT_RESUME1); + } + + ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF_CRITICAL(!__ssx_thread_is_active(thread), + SSX_INVALID_THREAD_AT_RESUME2, + &ctx); + } + + if (!__ssx_thread_is_mapped(thread)) { + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF_CRITICAL(__ssx_priority_map[thread->priority] != 0, + SSX_PRIORITY_IN_USE_AT_RESUME, + &ctx); + } + __ssx_thread_map(thread); + __ssx_schedule(); + } + + ssx_critical_section_exit(&ctx); + + return SSX_OK; +} + + +/// Suspend a thread +/// +/// Any active thread can be suspended. A suspended thread 1) remains active +/// but will not be scheduled; 2) relinquishes its priority assignment, +/// allowing another thread to be resumed at the suspended thread's priority; +/// and 3) disassociates from any semaphore mutual exclusion it may have been +/// participating in. +/// +/// If a sleeping thread is suspended, the sleep timer remains active but a +/// timeout of the timer simply marks the thread as runnable, but does not +/// resume the thread. +/// +/// If a thread blocked on a semaphore is suspended, the thread no longer +/// participates in the semaphore mutual exclusion. If the thread is later +/// resumed it will attempt to acquire the semaphore again the next time it +/// runs (unless it was blocked with a timeout and the timeout has expired). +/// +/// If a thread blocked on a semaphore with timeout is suspended, the +/// semaphore timeout timer continues to run. If the timer times out while the +/// thread is suspended the thread is simply marked runnable. If the thread is +/// later resumed, the suspended call of \c ssx_semaphore_pend() will return the +/// timeout code -SSX_SEMAPHORE_PEND_TIMED_OUT. +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion, including calls on a \a thread that is +/// already suspended. +/// +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was called from a critical +/// interrupt context. +/// +/// \retval -SSX_INVALID_THREAD_AT_SUSPEND1 The \a thread is a null (0) pointer +/// +/// \retval -SSX_INVALID_THREAD_AT_SUSPEND2 The \a thread is not active, +/// i.e. has completed or been deleted. + +int +ssx_thread_suspend(SsxThread *thread) +{ + SsxMachineContext ctx; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); + SSX_ERROR_IF((thread == 0), SSX_INVALID_THREAD_AT_SUSPEND1); + } + + ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF_CRITICAL(!__ssx_thread_is_active(thread), + SSX_INVALID_THREAD_AT_SUSPEND2, + &ctx); + } + + if (__ssx_thread_is_mapped(thread)) { + + SSX_TRACE_THREAD_SUSPENDED(thread->priority); + __ssx_thread_unmap(thread); + __ssx_schedule(); + } + + ssx_critical_section_exit(&ctx); + + return SSX_OK; +} + + +/// Delete a thread +/// +/// Any active thread can be deleted. If a thread is deleted it is removed +/// from the run queue, deleted from the timer queue (if sleeping or blocked +/// on a semaphore with timeout), and deleted from the semaphore mutual +/// exclusion if blocked on a semaphore. The thread control block is then +/// marked as deleted. +/// +/// Once a thread has completed or been deleted the thread structure and +/// thread stack areas can be used for other purposes. +/// +/// \param thread The thread to delete +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors. If a +/// thread deletes itself this API does not return at all. +/// +/// \retval 0 Successful completion, including calls on a \a thread that has +/// completed or had already been deleted. +/// +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was called from a critical +/// interrupt context. +/// +/// \retval -SSX_INVALID_THREAD_AT_DELETE The \a thread is a null (0) pointer. + +int +ssx_thread_delete(SsxThread *thread) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); + SSX_ERROR_IF(thread == 0, SSX_INVALID_THREAD_AT_DELETE); + } + + __ssx_thread_delete(thread, SSX_THREAD_STATE_DELETED); + + return SSX_OK; +} + + +/// Complete a thread +/// +/// If a thread ever returns from the subroutine defining the thread entry +/// point, the thread is removed from all SSX kernel data structures and +/// marked completed. The thread routine can also use the API ssx_complete() +/// to make this more explicit if desired. SSX makes no distinction between +/// completed and deleted threads, but provides these indications for +/// the benefit of the application. +/// +/// Note that this API is only available from the current thread to mark its +/// own completion. +/// +/// Once a thread has completed or been deleted the thread structure and +/// thread stack areas can be used for other purposes. +/// +/// Any return value indicates an error; see \ref ssx_errors. In the event of +/// a successful completion this API does not return to the caller, which is +/// always the thread context being completed. +/// +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was not called from a thread +/// context. + +// Note: Casting __ssx_current_thread removes the 'volatile' attribute. + +int +ssx_complete(void) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_UNLESS_THREAD_CONTEXT(); + } + + __ssx_thread_delete((SsxThread *)__ssx_current_thread, + SSX_THREAD_STATE_COMPLETED); + + return SSX_OK; +} + + +/// Sleep a thread until an absolute time +/// +/// \param time An absolute time as measured by the SSX timebase +/// +/// Threads can use this API to sleep until an absolute time. Sleeping threads +/// are not scheduled, although they maintain their priorities. This differs +/// from thread suspension, where the suspended thread relinquishes its +/// priority. When the sleep timer times out the thread becomes runnable +/// again, and will run as soon as it becomes the highest-priority mapped +/// runnable thread. +/// +/// Sleeping threads may also be later suspended. In this case the Sleep timer +/// continues to run, and if it times out before the thread is resumed the +/// thread will be immediately runnable when it is resumed. +/// +/// See the SSX specification for a full discussion of how SSX handles +/// scheduling events at absolute times "in the past". Briefly stated, if the +/// \a time is in the past, the thread will Sleep for the briefest possible +/// period supported by the hardware. +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion. +/// +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was not called from a thread +/// context. + +// Note: Casting __ssx_current_thread removes the 'volatile' attribute. + +int +ssx_sleep_absolute(SsxTimebase time) +{ + SsxMachineContext ctx; + SsxThread *current; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_UNLESS_THREAD_CONTEXT(); + } + + ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); + + current = (SsxThread *)__ssx_current_thread; + + current->timer.timeout = time; + __ssx_timer_schedule(&(current->timer)); + + current->flags |= SSX_THREAD_FLAG_TIMER_PEND; + + SSX_TRACE_THREAD_SLEEP(current->priority); + + __ssx_thread_queue_delete(&__ssx_run_queue, current->priority); + __ssx_schedule(); + + current->flags &= ~(SSX_THREAD_FLAG_TIMER_PEND | SSX_THREAD_FLAG_TIMED_OUT); + + ssx_critical_section_exit(&ctx); + + return SSX_OK; +} + +/// Sleep a thread for an interval relative to the current time. +/// +/// \param interval A time interval relative to the current timebase. +/// +/// Threads can use this API to sleep for a time relative to the current +/// timebase. The absolute timeout is \c ssx_timebase_get() + \a interval. +/// +/// Sleeping threads are not scheduled, although they maintain their +/// priorities. This differs from thread suspension, where the suspended +/// thread relinquishes its priority. When the sleep timer times out the +/// thread becomes runnable again, and will run as soon as it becomes the +/// highest-priority mapped runnable thread. +/// +/// Sleeping threads may also be later suspended. In this case the Sleep timer +/// continues to run, and if it times out before the thread is resumed the +/// thread will be immediately runnable when it is resumed. +/// +/// See the SSX specification for a full discussion of how SSX handles +/// scheduling events at absolute times "in the past". Briefly stated, if the +/// \a interval is 0 or is so small that the absolute time becomes a "past" +/// time before the Sleep is actually scheduled, the thread will Sleep for the +/// briefest possible period supported by the hardware. +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion. +/// +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD The API was not called from a thread +/// context. + +int +ssx_sleep(SsxInterval interval) +{ + return ssx_sleep_absolute(ssx_timebase_get() + interval); +} + + +/// Get information about a thread. +/// +/// \param thread A pointer to the SsxThread to query +/// +/// \param state The value returned through this pointer is the current state +/// of the thread; See \ref ssx_thread_states. The caller can set this +/// parameter to the null pointer (0) if this information is not required. +/// +/// \param priority The value returned through this pointer is the current +/// priority of the thread. The caller can set this parameter to the null +/// pointer (0) if this information is not required. +/// +/// \param runnable The value returned through this pointer is 1 if the thread +/// is in state SSX_THREAD_STATE_MAPPED and is currently in the run queue +/// (i.e., neither blocked on a semaphore nor sleeping), otherwise 0. The +/// caller can set this parameter to the null pointer (0) if this information +/// is not required. +/// +/// The information returned by this API can only be guaranteed consistent if +/// the API is called from an SSX_NONCRITICAL critical section. Since the +/// implementation of this API does not enforce a critical section, it is not +/// an error to call this API from a critical interrupt context. +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_THREAD_AT_INFO The \a thread is a null (0) pointer. + +int +ssx_thread_info_get(SsxThread *thread, + SsxThreadState *state, + SsxThreadPriority *priority, + int *runnable) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(thread == 0, SSX_INVALID_THREAD_AT_INFO); + } + + if (state) { + *state = thread->state; + } + if (priority) { + *priority = thread->priority; + } + if (runnable) { + *runnable = ((thread->state == SSX_THREAD_STATE_MAPPED) && + __ssx_thread_queue_member(&__ssx_run_queue, + thread->priority)); + } + return SSX_OK; +} + + +/// Change the priority of a thread. +/// +/// \param thread The thread whose priority will be changed +/// +/// \param new_priority The new priority of the thread +/// +/// \param old_priority The value returned through this pointer is the +/// old priority of the thread prior to the change. The caller can set +/// this parameter to the null pointer (0) if this information is not +/// required. +/// +/// Thread priorities can be changed by the \c ssx_thread_priority_change() +/// API. This call will fail if the thread pointer is invalid or if the thread +/// is mapped and the new priority is currently in use. The call will succeed +/// even if the \a thread is suspended, completed or deleted. The +/// application-level scheduling algorithm is completely responsible for the +/// correctness of the application in the event of suspended, completed or +/// deleted threads. +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion, including the redundant case of +/// attempting to change the priority of the thread to its current priority. +/// +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD the API was called from a critical +/// interrupt context. +/// +/// \retval -SSX_INVALID_THREAD_AT_CHANGE The \a thread is null (0) or +/// otherwise invalid. +/// +/// \retval -SSX_INVALID_ARGUMENT_THREAD_CHANGE The \a new_priority is invalid. +/// +/// \retval -SSX_PRIORITY_IN_USE_AT_CHANGE The \a thread is mapped and the \a +/// new_priority is currently in use by another thread. + +int +ssx_thread_priority_change(SsxThread *thread, + SsxThreadPriority new_priority, + SsxThreadPriority *old_priority) +{ + SsxMachineContext ctx; + SsxThreadPriority priority; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); + SSX_ERROR_IF(thread == 0, SSX_INVALID_THREAD_AT_CHANGE); + SSX_ERROR_IF(new_priority > SSX_THREADS, + SSX_INVALID_ARGUMENT_THREAD_CHANGE); + } + + ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); + + priority = thread->priority; + + if (priority != new_priority) { + + if (!__ssx_thread_is_mapped(thread)) { + + thread->priority = new_priority; + + } else { + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF_CRITICAL(__ssx_priority_map[new_priority] != 0, + SSX_PRIORITY_IN_USE_AT_CHANGE, + &ctx); + } + + __ssx_thread_unmap(thread); + thread->priority = new_priority; + __ssx_thread_map(thread); + __ssx_schedule(); + } + } + + if (old_priority) { + *old_priority = priority; + } + + ssx_critical_section_exit(&ctx); + + return SSX_OK; +} + + +/// Return a pointer to the thread (if any) mapped at a given priority. +/// +/// \param priority The thread priority of interest +/// +/// \param thread The value returned through this pointer is a pointer to the +/// thread currently mapped at the given priority level. If no thread is +/// mapped, or if the \a priority is the priority of the idle thread, the +/// pointer returned will be null (0). +/// +/// The information returned by this API can only be guaranteed consistent if +/// the API is called from an SSX_NONCRITICAL critical section. Since the +/// implementation of this API does not require a critical section, it is not +/// an error to call this API from a critical interrupt context. +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion. +/// +/// \retval -SSX_INVALID_ARGUMENT_THREAD_PRIORITY The \a priority is invalid +/// or the \a thread parameter is null (0). + +int +ssx_thread_at_priority(SsxThreadPriority priority, + SsxThread **thread) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((priority > SSX_THREADS) || (thread == 0), + SSX_INVALID_ARGUMENT_THREAD_PRIORITY); + } + + *thread = __ssx_thread_at_priority(priority); + + return SSX_OK; +} + + +/// Swap thread priorities +/// +/// \param thread_a A pointer to an initialized SsxThread +/// +/// \param thread_b A pointer to an initialized SsxThread +/// +/// This API swaps the priorities of \a thread_a and \a thread_b. The API is +/// provided to support general and efficient application-directed scheduling +/// algorithms. The requirements on the \a thread_a and \a thread_b arguments +/// are that they are valid pointers to initialized SsxThread structures, that +/// the current thread priorities of both threads are legal, and that if a +/// thread is currently mapped, that the new thread priority is not otherwise +/// in use. +/// +/// The API does not require either thread to be mapped, or even to be active. +/// It is legal for one or both of the swap partners to be suspended, deleted +/// or completed threads. The application is completely responsible for the +/// correctness of scheduling algorithms that might operate on inactive or +/// suspended threads. +/// +/// The API does not change the mapped status of a thread. A thread will be +/// mapped after the call of ssx_thread_priority_swap() if and only if it was +/// mapped prior to the call. If the new priority of a mapped thread is +/// currently in use (by a thread other than the swap partner), then the +/// SSX_PRIORITY_IN_USE_AT_SWAP error is signalled and the swap does not take +/// place. This could only happen if the swap partner is not currently mapped. +/// +/// It is legal for a thread to swap its own priority with another thread. The +/// degenerate case that \a thread_a and \a thread_b are equal is also legal - +/// but has no effect. +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion, including the redundant cases that do not +/// actually change priorities, or the cases that assign new priorities to +/// suspended, completed or deleted threads. +/// +/// \retval -SSX_ILLEGAL_CONTEXT_THREAD the API was called from a critical +/// interrupt context. +/// +/// \retval -SSX_INVALID_THREAD_AT_SWAP1 One or both of \a thread_a and +/// \a thread_b is null (0) or otherwise invalid, +/// +/// \retval -SSX_INVALID_THREAD_AT_SWAP2 the priorities of One or both of +/// \a thread_a and \a thread_b are invalid. +/// +/// \retval -SSX_INVALID_ARGUMENT One or both of the priorities +/// of \a thread_a and \a thread_b is invalid. +/// +/// \retval -SSX_PRIORITY_IN_USE_AT_SWAP Returned if a thread is mapped and the +/// new thread priority is currently in use by another thread (other than the +/// swap partner). + +int +ssx_thread_priority_swap(SsxThread* thread_a, SsxThread* thread_b) +{ + SsxMachineContext ctx; + SsxThreadPriority priority_a, priority_b; + int mapped_a, mapped_b; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); + SSX_ERROR_IF((thread_a == 0) || (thread_b == 0), + SSX_INVALID_THREAD_AT_SWAP1); + } + + ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); + + if (thread_a != thread_b) { + + mapped_a = __ssx_thread_is_mapped(thread_a); + mapped_b = __ssx_thread_is_mapped(thread_b); + priority_a = thread_a->priority; + priority_b = thread_b->priority; + + if (SSX_ERROR_CHECK_API) { + int priority_in_use; + SSX_ERROR_IF_CRITICAL((priority_a > SSX_THREADS) || + (priority_b > SSX_THREADS), + SSX_INVALID_THREAD_AT_SWAP2, + &ctx); + priority_in_use = + (mapped_a && !mapped_b && + (__ssx_thread_at_priority(priority_b) != 0)) || + (!mapped_a && mapped_b && + (__ssx_thread_at_priority(priority_a) != 0)); + SSX_ERROR_IF_CRITICAL(priority_in_use, + SSX_PRIORITY_IN_USE_AT_SWAP, &ctx); + } + + if (mapped_a) { + __ssx_thread_unmap(thread_a); + } + if (mapped_b) { + __ssx_thread_unmap(thread_b); + } + thread_a->priority = priority_b; + thread_b->priority = priority_a; + if (mapped_a) { + __ssx_thread_map(thread_a); + } + if (mapped_b) { + __ssx_thread_map(thread_b); + } + __ssx_schedule(); + } + + ssx_critical_section_exit(&ctx); + + return SSX_OK; +} + + +#undef __SSX_THREAD_CORE_C__ diff --git a/src/ssx/ssx/ssx_thread_init.c b/src/ssx/ssx/ssx_thread_init.c new file mode 100755 index 0000000..c1a71b5 --- /dev/null +++ b/src/ssx/ssx/ssx_thread_init.c @@ -0,0 +1,140 @@ +// $Id: ssx_thread_init.c,v 1.2 2014/02/03 01:30:44 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_thread_init.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_thread_init.c +/// \brief SSX thread API initialization routines +/// +/// The entry points in this file are routines that are typically used during +/// initialization, and their code space could be deallocated and recovered if +/// no longer needed by the application after initialization. + +#include "ssx.h" + +/// Create (initialize) a thread +/// +/// \param thread A pointer to an SsxThread structure to initialize +/// +/// \param thread_routine The subroutine that implements the thread +/// +/// \param arg Private data to be passed as the argument to the thread +/// routine when it begins execution +/// +/// \param stack The stack space of the thread +/// +/// \param stack_size The size of the stack in bytes +/// +/// \param priority The initial priority of the thread +/// +/// The \a thread argument must be a pointer to an uninitialized or completed +/// or deleted thread. This \c SsxThread structure \em is the thread, so this +/// memory area must not be modified by the application until the thread +/// completes or is deleted. SSX can not tell if an SsxThread structure is +/// currently in use as a thread control block.ssx_thread_create() will +/// silently overwrite an SsxThread structure that is currently in use. +/// +/// The stack area must be large enough to hold the dynamic stack requirements +/// of the entry point routine, and all subroutines and functions that might +/// be invoked on any path from the entry point. The stack must also always +/// be able to hold the thread context in the event the thread is preempted, +/// plus other critical context. SSX aligns stack areas in machine-specific +/// ways, so that the actual stack area may reduced in size slightly if it is +/// not already aligned. +/// +/// Threads are created runnable but unmapped. A newly created thread will +/// not be eligible to run until a call of ssx_thread_resume() targets the +/// thread. +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_THREAD_AT_CREATE The \a thread is a null (0) pointer. +/// +/// \retval -SSX_ILLEGAL_CONTEXT The API was called from a critical interrupt +/// context. +/// +/// \retval -SSX_INVALID_ARGUMENT_THREAD1 the \a thread_routine is null (0) +/// +/// \retval -SSX_INVALID_ARGUMENT_THREAD2 the \a priority is invalid, +/// +/// \retval -SSX_INVALID_ARGUMENT_THREAD3 the stack area wraps around +/// the end of memory. +/// +/// \retval -SSX_STACK_OVERFLOW The stack area at thread creation is smaller +/// than the minimum safe size. + +int +ssx_thread_create(SsxThread *thread, + SsxThreadRoutine thread_routine, + void *arg, + SsxAddress stack, + size_t stack_size, + SsxThreadPriority priority) +{ + int rc; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); + SSX_ERROR_IF(thread == 0, SSX_INVALID_THREAD_AT_CREATE); + SSX_ERROR_IF((thread_routine == 0) || + (priority >= SSX_THREADS), + SSX_INVALID_ARGUMENT_THREAD1); + } + + rc = __ssx_stack_init(&stack, &stack_size); + if (rc) { + return rc; + } + + thread->saved_stack_pointer = stack; + thread->stack_base = stack; + + if (SSX_STACK_DIRECTION < 0) { + + thread->stack_limit = stack - stack_size; + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(thread->stack_limit > thread->stack_base, + SSX_INVALID_ARGUMENT_THREAD2); + } + + } else { + + thread->stack_limit = stack + stack_size; + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(thread->stack_limit < thread->stack_base, + SSX_INVALID_ARGUMENT_THREAD3); + } + } + + thread->semaphore = 0; + thread->priority = priority; + thread->state = SSX_THREAD_STATE_SUSPENDED_RUNNABLE; + thread->flags = 0; + + ssx_timer_create_nonpreemptible(&(thread->timer), + __ssx_thread_timeout, + (void *)thread); + + __ssx_thread_context_initialize(thread, thread_routine, arg); + + return rc; +} + + + + + + + + + + + + + + diff --git a/src/ssx/ssx/ssx_timer_core.c b/src/ssx/ssx/ssx_timer_core.c new file mode 100755 index 0000000..8153acf --- /dev/null +++ b/src/ssx/ssx/ssx_timer_core.c @@ -0,0 +1,447 @@ +// $Id: ssx_timer_core.c,v 1.2 2014/02/03 01:30:44 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_timer_core.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_timer_core.c +/// \brief SSX portable kernel timer handler +/// +/// This file contains core routines that would be needed by any application +/// that requires SSX timer support at runtime. +/// +/// SSX implements a 'tickless' kernel - all events are scheduled at absolute +/// times of the SSX timebase. This approach gives the application full +/// control over granularity of event scheduling. Scheduling in absolute time +/// opens up the possibility of scheduling events "in the past". SSX +/// uniformly handles this case by scheduling "past" events to occur 1 +/// timebase tick in the future, so that timer callbacks are always run in the +/// expected noncritical interrupt context. +/// +/// SSX implements the time queue as a simple unordered list of events, plus a +/// dedicated variable that holds the earliest timeout of any event in the +/// list. This is thought to be an appropriate data structure for the +/// following reasons: +/// +/// - SSX applications will be small and will not schedule a large number of +/// events. Therefore the cost of scanning the list each time an event times +/// out is balanced against the cost of maintaining the list as a sorted data +/// structure each time an event is added or removed from the event queue. +/// +/// - SSX applications may schedule and cancel many, many more events (safety +/// timeouts) than are ever allowed to expire. Events can be added and deleted +/// from the simple DEQUE very quickly since there is no sorting +/// overhead. +/// +/// Events are added to the queue simply by placing them at the end of the +/// queue. If the new event times out earlier than the previous earliest +/// event, the hardware timeout is rescheduled for the new event time. Events +/// are deleted from the queue (cancelled) simply by deleting them. Deletion +/// does not affect the hardware timeout, even if the deleted event would have +/// been the next to time out. It is not an error for the timer handler to +/// take a timer interrupt and find no events pending. Pending events can +/// also be rescheduled in place. +/// +/// When a timeout occurs the event list is scanned from the beginning, and +/// any event that has timed out is rescheduled if necessary (periodic events) +/// and its callback is processed. Since event and callback processing take +/// time, the list is potentially scanned multiple times until there are no +/// more timed-out events in the list. +/// +/// Note that callbacks are not necessarily processed in time-order. In this +/// sense the SSX time queue is like a traditional tick-based time queue in +/// that events are effectively lumped into groups of events that time out +/// together. In a tick-based kernel the 'lump' is the tick interval; here +/// the 'lump' is a variable interval that corresponds to the time it takes to +/// process the entire event list. +/// +/// Timer callbacks are typically run with interrupt preemption enabled. +/// Special callbacks may run without preemption. This is the only part of +/// the SSX kernel where data structures of indeterminate size are processed. +/// During processing of the event list by the timer interrupt handler, the +/// consideration of each event always includes a window of preemptability. + +#define __SSX_TIMER_CORE_C__ + +#include "ssx.h" + +// This routine is only used in this file, and will always be called in +// critical section. + +static inline int +timer_active(SsxTimer* timer) +{ + return ssx_deque_is_queued((SsxDeque*)timer); +} + + +// This is the kernel version of ssx_timer_cancel(). +// +// This routine is used here and by thread and semaphore routines. +// Noncritical interrupts must be disabled at entry. +// +// If the timer is active, then there is a special case if we are going to +// delete the 'cursor' - that is the timer that __ssx_timer_handler() is going +// to handle next. In this case we need to move the cursor to the next timer +// in the queue. +// +// Note that cancelling a timer does not cause a re-evaluation of the next +// timeout. This will happen naturally when the current timeout expires. + +int +__ssx_timer_cancel(SsxTimer *timer) +{ + int rc; + SsxDeque* timer_deque = (SsxDeque*)timer; + SsxTimeQueue* tq = &__ssx_time_queue; + + if (!timer_active(timer)) { + + rc = -SSX_TIMER_NOT_ACTIVE; + + } else { + + if (timer_deque == tq->cursor) { + tq->cursor = tq->cursor->next; + } + ssx_deque_delete(timer_deque); + rc = 0; + } + return rc; +} + + +// This is the kernel version of ssx_timer_schedule(). +// +// This routine is used here and by thread and semaphore routines. +// Noncritical interrupts must be disabled at entry. +// +// Unless the timer is already active it is enqueued in the doubly-linked +// timer list by inserting the timer at the end of the queue. Then the +// hardware timeout is scheduled if necessary. If the time queue 'cursor' != 0 +// we are in the midst of processing the time queue, and the end of time queue +// processing will schedule the next hardware timemout. + +void +__ssx_timer_schedule(SsxTimer* timer) +{ + SsxTimeQueue* tq = &__ssx_time_queue; + + if (!timer_active(timer)) { + ssx_deque_push_back((SsxDeque*)tq, (SsxDeque*)timer); + } + + if (timer->timeout < tq->next_timeout) { + tq->next_timeout = timer->timeout; + if (tq->cursor == 0) { + __ssx_schedule_hardware_timeout(tq->next_timeout); + } + } +} + + +// The tickless timer mechanism has timed out. Note that due to timer +// deletions and other factors, there may not actually be a timer in the queue +// that has timed out - but it doesn't matter (other than for efficiency). +// +// Noncritical interrupts are (must be) disabled at entry, and this invariant +// is checked. This routine must not be entered reentrantly. +// +// First, time out any timers that have expired. Timers in the queue are +// unordered, so we have to check every one. Since passing through the +// loop takes time, we may have to make multiple passes until we know +// that there are no timers in the queue that have already timed +// out. Note that it would also work to only go through the loop once and +// let the hardware scheduler take care of looping, but that would imply +// more overhead than the current implementation. +// +// On each pass through the loop tq->next_timeout computes the minimum timeout +// of events remaining in the queue. This is the only part of the kernel that +// searches a list of indefinite length. Kernel interrupt latency is mitigated +// by running callbacks with interrupts disabled either during or after the +// call for timed out events, and also after every check for events that have +// not timed out. +// +// Because interrupt preemption is enabled during processing, and preempting +// handlers may invoke time queue operations, we need to establish a pointer +// to the next entry to be examined (tq->cursor) before enabling interupts. +// It's possible that this pointer will be changed by other interrupt handlers +// that cancel the timer pointed to by tq->cursor. +// +// The main loop iterates on the SsxDeque form of the time queue, casting each +// element back up to the SsxTimer as it is processed. + +void +__ssx_timer_handler() +{ + SsxTimeQueue* tq; + SsxTimebase now; + SsxTimer* timer; + SsxDeque* timer_deque; + SsxTimerCallback callback; + + tq = &__ssx_time_queue; + + if (SSX_ERROR_CHECK_KERNEL) { + if (tq->cursor != 0) { + SSX_PANIC(SSX_TIMER_HANDLER_INVARIANT); + } + } + + while ((now = ssx_timebase_get()) >= tq->next_timeout) { + + tq->next_timeout = SSX_TIMEBASE_MAX; + timer_deque = ((SsxDeque*)tq)->next; + + while (timer_deque != (SsxDeque*)tq) { + + timer = (SsxTimer*)timer_deque; + tq->cursor = timer_deque->next; + + if (timer->timeout <= now) { + + // The timer timed out. It is removed from the queue unless + // it is a peridic timer that needs to be rescheduled. We do + // rescheduling here in the critical section to correctly + // handle timers whose callbacks may cancel the timer. The + // timer is rescheduled in absolute time. + // + // The callback may be made with interrupt preemption enabled + // or disabled. However to mitigate kernel interrupt latency + // we go ahead and open up to interrupts after the callback if + // the callback itself was not preemptible. + + if (timer->period == 0) { + ssx_deque_delete(timer_deque); + } else { + timer->timeout += timer->period; + tq->next_timeout = MIN(timer->timeout, tq->next_timeout); + } + + callback = timer->callback; + if (callback) { + if (timer->options & SSX_TIMER_CALLBACK_PREEMPTIBLE) { + ssx_interrupt_preemption_enable(); + callback(timer->arg); + } else { + callback(timer->arg); + ssx_interrupt_preemption_enable(); + } + } + ssx_interrupt_preemption_disable(); + + } else { + + // This timer has not timed out. Its timeout will simply + // participate in the computation of the next timeout. For + // interrupt latency reasons we always allow a period of + // interrupt preemption. + + tq->next_timeout = MIN(timer->timeout, tq->next_timeout); + ssx_interrupt_preemption_enable(); + ssx_interrupt_preemption_disable(); + } + + timer_deque = tq->cursor; + } + } + + tq->cursor = 0; + + // Finally, reschedule the next timeout + + __ssx_schedule_hardware_timeout(tq->next_timeout); +} + + +/// Schedule a timer in absolute time. +/// +/// \param timer The SsxTimer to schedule. +/// +/// \param timeout The timer will be scheduled to time out at this absolute +/// time. Note that if the \a timeout is less than the current time then the +/// timer will be scheduled at a minimum timeout in the future and the +/// callback will be executed in an interrupt context. +/// +/// \param period If non-0, then when the timer times out it will rescheduled +/// to time out again at the absolute time equal to the last timeout time plus +/// the \a period. By convention a \a period of 0 indicates a one-shot +/// timer that is not rescheduled. +/// +/// Once created with ssx_timer_create() a timer can be \e scheduled, which +/// queues the timer in the kernel time queue. It is not an error to call +/// ssx_timer_schedule() on a timer that is already scheduled in the time +/// queue - the timer is simply rescheduled with the new characteristics. +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_TIMER_AT_SCHEDULE A a null (0) pointer was provided as +/// the \a timer argument. +/// +/// \retval -SSX_ILLEGAL_CONTEXT_TIMER The call was made from a critical +/// interrupt context. + +int +ssx_timer_schedule_absolute(SsxTimer *timer, + SsxTimebase timeout, + SsxInterval period) + +{ + SsxMachineContext ctx; + + ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(timer == 0, SSX_INVALID_TIMER_AT_SCHEDULE); + SSX_ERROR_IF(__ssx_kernel_context_critical_interrupt(), + SSX_ILLEGAL_CONTEXT_TIMER); + } + + timer->timeout = timeout; + timer->period = period; + __ssx_timer_schedule(timer); + + ssx_critical_section_exit(&ctx); + + return SSX_OK; +} + + +/// Schedule a timer for an interval relative to the current time. +/// +/// \param timer The SsxTimer to schedule. +/// +/// \param interval The timer will be scheduled to time out at the current +/// time (ssx_timebase_get()) plus this \a interval. +/// +/// \param period If non-0, then when the timer times out it will rescheduled +/// to time out again at the absolute time equal to the last timeout time plus +/// the \a period. By convention a \a period of 0 indicates a one-shot +/// timer that is not rescheduled. +/// +/// Once created with ssx_timer_create() a timer can be \e scheduled, which +/// queues the timer in the kernel time queue. It is not an error to call \c +/// ssx_timer_schedule() on a timer that is already scheduled in the time +/// queue - the timer is simply rescheduled with the new characteristics. +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_TIMER_AT_SCHEDULE A a null (0) pointer was provided as +/// the \a timer argument. +/// +/// \retval -SSX_ILLEGAL_CONTEXT_TIMER The call was made from a critical +/// interrupt context. + +int +ssx_timer_schedule(SsxTimer *timer, + SsxInterval interval, + SsxInterval period) +{ + return ssx_timer_schedule_absolute(timer, + ssx_timebase_get() + interval, + period); +} + + +/// Cancel (dequeue) a timer. +/// +/// \param timer The SsxTimer to cancel. +/// +/// Timers can be canceled at any time. It is never an error to call +/// ssx_timer_cancel() on an SsxTimer object after it is created. Memory used +/// by an SsxTimer can be safely reused for another purpose after a successful +/// call ofssx_timer_cancel(). +/// +/// Return values other than SSX_OK (0) are not necessarily errors; see \ref +/// ssx_errors +/// +/// The following return codes are non-error codes: +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_TIMER_NOT_ACTIVE The \a timer is not currently scheduled, +/// i.e. it was never scheduled or has timed out. This code is returned for +/// information only and is not considered an error. +/// +/// The following return codes are error codes: +/// +/// \retval -SSX_INVALID_TIMER_AT_CANCEL The \a timer is a null (0) pointer. +/// +/// \retval -SSX_ILLEGAL_CONTEXT_TIMER The call was made from a critical +/// interrupt context. +/// + +int +ssx_timer_cancel(SsxTimer *timer) +{ + SsxMachineContext ctx; + int rc = SSX_OK; + + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF_CRITICAL_INTERRUPT_CONTEXT(); + SSX_ERROR_IF(timer == 0, SSX_INVALID_TIMER_AT_CANCEL); + } + + ssx_critical_section_enter(SSX_NONCRITICAL, &ctx); + + rc = __ssx_timer_cancel(timer); + + ssx_critical_section_exit(&ctx); + + return rc; +} + + +/// Get information about a timer. +/// +/// \param timer The SsxTimer to query +/// +/// \param timeout The API returns the absolute timeout of the timer through +/// this pointer. If the timer is active, this is the current timeout. If +/// the timer has timed out then this is the previous absolute timeout. If +/// the timer was never scheduled this will be 0. The caller can set this +/// parameter to the null pointer (0) if this information is not required. +/// +/// \param active If the value returned through this pointer is 1 then the +/// timer is active (currently scheduled), otherwise the value will be 0 +/// indicating an inactive timer. The caller can set this parameter to the +/// null pointer (0) if this information is not required. +/// +/// The information returned by this API can only be guaranteed consistent if +/// the API is called from an SSX_NONCRITICAL critical section. Since the +/// implementation of this API does not require a critical section, it is not +/// an error to call this API from a critical interrupt context. +/// +/// Return values other than SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_TIMER_AT_INFO The \a timer is a null (0) pointer. + +int +ssx_timer_info_get(SsxTimer *timer, + SsxTimebase *timeout, + int *active) + +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF(timer == 0, SSX_INVALID_TIMER_AT_INFO); + } + + if (timeout) { + *timeout = timer->timeout; + } + if (active) { + *active = timer_active(timer); + } + + return SSX_OK; +} + +#undef __SSX_TIMER_CORE_C__ diff --git a/src/ssx/ssx/ssx_timer_init.c b/src/ssx/ssx/ssx_timer_init.c new file mode 100755 index 0000000..6c35ea6 --- /dev/null +++ b/src/ssx/ssx/ssx_timer_init.c @@ -0,0 +1,124 @@ +// $Id: ssx_timer_init.c,v 1.2 2014/02/03 01:30:44 daviddu Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssx_timer_init.c,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ssx_timer_init.c +/// \brief SSX timer initialization +/// +/// The entry points in this file might only be used during initialization of +/// the application. In this case the code space for these routines could be +/// recovered and reused after initialization. + +#include "ssx.h" + +// Implementation of timer creation + +static int +_ssx_timer_create(SsxTimer *timer, + SsxTimerCallback callback, + void *arg, + int options) +{ + if (SSX_ERROR_CHECK_API) { + SSX_ERROR_IF((timer == 0), SSX_INVALID_TIMER_AT_CREATE); + } + + ssx_deque_element_create((SsxDeque*)timer); + timer->timeout = 0; + timer->period = 0; + timer->callback = callback; + timer->arg = arg; + timer->options = options; + + return SSX_OK; +} + + +/// Create (initialize) a preemptible timer. +/// +/// \param timer The SsxTimer to initialize. +/// +/// \param callback The timer callback +/// +/// \param arg Private data provided to the callback. +/// +/// Once created with ssx_timer_create() a timer can be scheduled with +/// ssx_timer_schedule() or ssx_timer_schedule_absolute(), which queues the +/// timer in the kernel time queue. Timers can be cancelled by a call of +/// ssx_timer_cancel(). +/// +/// Timers created with ssx_timer_create() are always run as noncritical +/// interrupt handlers with interrupt preemption enabled. Timer callbacks are +/// free to enter critical sections of any priorioty if required, but must +/// always exit with noncritical interrupts enabled. +/// +/// Caution: SSX has no way to know if an SsxTimer structure provided to +/// ssx_timer_create() is safe to use as a timer, and will silently modify +/// whatever memory is provided. +/// +/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_TIMER_AT_CREATE The \a timer is a null (0) pointer. + +int +ssx_timer_create(SsxTimer *timer, + SsxTimerCallback callback, + void *arg) +{ + return _ssx_timer_create(timer, callback, arg, + SSX_TIMER_CALLBACK_PREEMPTIBLE); +} + + +/// Create (initialize) a nonpreemptible timer. +/// +/// \param timer The SsxTimer to initialize. +/// +/// \param callback The timer callback +/// +/// \param arg Private data provided to the callback. +/// +/// Once created with ssx_timer_create_preemptible() a timer can be scheduled +/// with ssx_timer_schedule() or ssx_timer_schedule_absolute(), which queues +/// the timer in the kernel time queue. Timers can be cancelled by a call of +/// ssx_timer_cancel(). +/// +/// Timers created with ssx_timer_create_nonpreemptible() are always run as +/// noncritical interrupt handlers with interrupt preemption disabled. Timer +/// callbacks are free to later enable preemption if desired, but must always +/// exit with noncritical interrupts disabled. +/// +/// \note The use of ssx_timer_create_nonpreemptible() should be rare, and the +/// timer callbacks should be short and sweet to avoid long interrupt +/// latencies for other interrupts. This API was initially introduced for use +/// by the SSX kernel itself when scheduling thread-timer callbacks to avoid +/// potential race conditions with other interrupts that may modify thread +/// state or the state of the time queue. Applications may also require this +/// facility to guarantee a consistent state in the event that other +/// interrupts may cancel the timer. +/// +/// Caution: SSX has no way to know if an SsxTimer structure provided to +/// ssx_timer_create() is safe to use as a timer, and will silently modify +/// whatever memory is provided. +/// +/// Return values other then SSX_OK (0) are errors; see \ref ssx_errors +/// +/// \retval 0 Successful completion +/// +/// \retval -SSX_INVALID_TIMER_AT_CREATE The \a timer is a null (0) pointer. + +int +ssx_timer_create_nonpreemptible(SsxTimer *timer, + SsxTimerCallback callback, + void *arg) +{ + return _ssx_timer_create(timer, callback, arg, 0); +} + + diff --git a/src/ssx/ssx/ssxssxfiles.mk b/src/ssx/ssx/ssxssxfiles.mk new file mode 100755 index 0000000..e78e986 --- /dev/null +++ b/src/ssx/ssx/ssxssxfiles.mk @@ -0,0 +1,35 @@ +# $Id: ssxssxfiles.mk,v 1.2 2014/06/26 13:02:00 cmolsen Exp $ +# $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ssx/ssxssxfiles.mk,v $ +# @file ssxpgpfiles.mk +# +# @brief mk for including pgp object files +# +# @page ChangeLogs Change Logs +# @section ssxpgpfiles.mk +# @verbatim +# +# +# Change Log ****************************************************************** +# Flag Defect/Feature User Date Description +# ------ -------------- ---------- ------------ ----------- +# @pb00E pbavari 03/11/2012 Makefile ODE support +# +# @endverbatim +# +########################################################################## +# Include +########################################################################## + + +########################################################################## +# Object Files +########################################################################## +SSX-C-SOURCES = ssx_core.c ssx_init.c ssx_stack_init.c + +SSX-TIMER-C-SOURCES += ssx_timer_core.c ssx_timer_init.c + +SSX-THREAD-C-SOURCES += ssx_thread_init.c ssx_thread_core.c \ + ssx_semaphore_init.c ssx_semaphore_core.c + +SSX_OBJECTS += $(SSX-C-SOURCES:.c=.o) + |