diff options
Diffstat (limited to 'pk/ppe42')
-rw-r--r-- | pk/ppe42/.empty | 0 | ||||
-rw-r--r-- | pk/ppe42/Makefile | 26 | ||||
-rw-r--r-- | pk/ppe42/div64.S | 248 | ||||
-rw-r--r-- | pk/ppe42/pk_port_types.h | 41 | ||||
-rw-r--r-- | pk/ppe42/pkppe42files.mk | 46 | ||||
-rw-r--r-- | pk/ppe42/ppe42.h | 825 | ||||
-rw-r--r-- | pk/ppe42/ppe42_asm.h | 608 | ||||
-rw-r--r-- | pk/ppe42/ppe42_boot.S | 169 | ||||
-rw-r--r-- | pk/ppe42/ppe42_cache.h | 102 | ||||
-rw-r--r-- | pk/ppe42/ppe42_context.h | 201 | ||||
-rw-r--r-- | pk/ppe42/ppe42_core.c | 126 | ||||
-rw-r--r-- | pk/ppe42/ppe42_exceptions.S | 501 | ||||
-rw-r--r-- | pk/ppe42/ppe42_gcc.c | 305 | ||||
-rw-r--r-- | pk/ppe42/ppe42_gcc.h | 72 | ||||
-rw-r--r-- | pk/ppe42/ppe42_init.c | 77 | ||||
-rw-r--r-- | pk/ppe42/ppe42_irq.h | 218 | ||||
-rw-r--r-- | pk/ppe42/ppe42_irq_core.c | 47 | ||||
-rw-r--r-- | pk/ppe42/ppe42_msr.h | 88 | ||||
-rwxr-xr-x | pk/ppe42/ppe42_scom.c | 79 | ||||
-rwxr-xr-x | pk/ppe42/ppe42_scom.h | 158 | ||||
-rw-r--r-- | pk/ppe42/ppe42_spr.h | 173 | ||||
-rw-r--r-- | pk/ppe42/ppe42_thread_init.S | 110 | ||||
-rw-r--r-- | pk/ppe42/ppe42_timebase.S | 116 |
23 files changed, 0 insertions, 4336 deletions
diff --git a/pk/ppe42/.empty b/pk/ppe42/.empty deleted file mode 100644 index e69de29b..00000000 --- a/pk/ppe42/.empty +++ /dev/null diff --git a/pk/ppe42/Makefile b/pk/ppe42/Makefile deleted file mode 100644 index 5bb2b566..00000000 --- a/pk/ppe42/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# This Makefile is designed to be invoked with the -I argument set to -# the location of the "pk.mk" for the build - -include img_defs.mk -include pkppe42files.mk - -ifeq "$(PK_TIMER_SUPPORT)" "1" -PPE42_OBJECTS += ${PPE42-TIMER-C-SOURCES:.c=.o} ${PPE42-TIMER-S-SOURCES:.S=.o} -endif - -ifeq "$(PK_THREAD_SUPPORT)" "1" -PPE42_OBJECTS += ${PPE42-THREAD-C-SOURCES:.c=.o} ${PPE42-THREAD-S-SOURCES:.S=.o} -endif - -OBJS := $(addprefix $(OBJDIR)/, $(PPE42_OBJECTS)) - -all: $(OBJS) - -$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) - -$(OBJDIR): - mkdir -p $(OBJDIR) - -ifneq ($(MAKECMDGOALS),clean) -include $(OBJS:.o=.d) -endif diff --git a/pk/ppe42/div64.S b/pk/ppe42/div64.S deleted file mode 100644 index 7d4b1ffa..00000000 --- a/pk/ppe42/div64.S +++ /dev/null @@ -1,248 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! 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 PK 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 "pk.h" - .list - - .global_function __ppe42_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. - */ - -__ppe42_udiv64: // PK - - /* push R30 & R31 onto the stack */ - stwu r1, -16(r1) - stvd r30, 8(r1) - - /* Save result pointers on volatile spare registers */ - ori r31, r8, 0 /* Save remainder address */ - ori r30, 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? */ - 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 */ - cmpwi cr0, r6, 0 /* dvd.lsw == 0? */ - beq cr0, 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(r30) - stw r3, 0(r30) - stw r8, 4(r31) /* rem.lsw */ - stw r7, 0(r31) /* rem.msw */ - b lab11 - -lab9: - /* Qoutient is 0, divisor > dividend */ - addi r0, r0, 0 - stw r3, 0(r31) /* Store remainder */ - stw r4, 4(r31) - stw r0, 0(r30) /* Set quotient to zero */ - stw r0, 4(r30) - b lab11 - -lab10: - /* Divisor is 0 */ - addi r0, r0, -1 - stw r0, 0(r31) /* Set remainder to zero */ - stw r0, 4(r31) - stw r0, 0(r30) /* Set quotient to zero */ - stw r0, 4(r30) - -lab11: - //pop r30 & r31 from stack - lvd r30, 8(r1) - lwz r1, 0(r1) - blr - .epilogue __ppe42_udiv64 diff --git a/pk/ppe42/pk_port_types.h b/pk/ppe42/pk_port_types.h deleted file mode 100644 index 1536b77b..00000000 --- a/pk/ppe42/pk_port_types.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __PK_PORT_TYPES_H__ -#define __PK_PORT_TYPES_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_port_types.h -/// \brief Type definitions required by the PK port. -/// -/// \todo GCC provides a portable version of cntlzw called __builtin_clz(). -/// We should make the PK 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 PK/port/chip headers are included. - -/// An PkIrqId is an integer in the range of valid interrupts defined by the -/// interrupt controller. - -typedef uint8_t PkIrqId; - -/// PK requires the port to define the type PkThreadQueue, which is a -/// priority queue (where 0 is the highest priority). This queue must be able -/// to handle PK_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 PK_THREADS if -/// the queue is empty. (Or a queue could be initialized with the PK_THREADS -/// entry always present - PK 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 PPE42 with 32 threads (implied), this is a job for a uint32_t and -/// cntlzw(). - -typedef uint32_t PkThreadQueue; - -#endif /* __PK_PORT_TYPES_H__ */ diff --git a/pk/ppe42/pkppe42files.mk b/pk/ppe42/pkppe42files.mk deleted file mode 100644 index 2ad2fa55..00000000 --- a/pk/ppe42/pkppe42files.mk +++ /dev/null @@ -1,46 +0,0 @@ -# @file pkppe42files.mk -# -# @brief mk for including ppe42 object files -# -# @page ChangeLogs Change Logs -# @section pkppe42files.mk -# @verbatim -# -# -# Change Log ****************************************************************** -# Flag Defect/Feature User Date Description -# ------ -------------- ---------- ------------ ----------- -# -# @endverbatim -# -########################################################################## -# Include Files -########################################################################## - - - -########################################################################## -# Object Files -########################################################################## -PPE42-C-SOURCES = ppe42_core.c \ - ppe42_init.c \ - ppe42_irq_core.c\ - ppe42_gcc.c\ - ppe42_scom.c - -PPE42-S-SOURCES = ppe42_boot.S \ - ppe42_exceptions.S\ - div64.S\ - ppe42_timebase.S - -PPE42-TIMER-C-SOURCES = -PPE42-TIMER-S-SOURCES = - -PPE42-THREAD-C-SOURCES += -PPE42-THREAD-S-SOURCES += ppe42_thread_init.S - - -PPE42_OBJECTS += $(PPE42-C-SOURCES:.c=.o) $(PPE42-S-SOURCES:.S=.o) - - - diff --git a/pk/ppe42/ppe42.h b/pk/ppe42/ppe42.h deleted file mode 100644 index 35d57bad..00000000 --- a/pk/ppe42/ppe42.h +++ /dev/null @@ -1,825 +0,0 @@ -#ifndef __PPE42_H__ -#define __PPE42_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42.h -/// \brief PPE42 port header for PK - -// Macros to define where declared code is actually compiled - -#ifdef __PPE42_C__ -#define IF__PPE42_CORE_C__(x) x -#define UNLESS__PPE42_CORE_C__(x) -#else -#define IF__PPE42_CORE_C__(x) -#define UNLESS__PPE42_CORE_C__(x) x -#endif - -#ifdef __PPE42_IRQ_CORE_C__ -#define IF__PPE42_IRQ_CORE_C__(x) x -#define UNLESS__PPE42_IRQ_CORE_C__(x) -#else -#define IF__PPE42_IRQ_CORE_C__(x) -#define UNLESS__PPE42_IRQ_CORE_C__(x) x -#endif - -#ifdef HWMACRO_GPE -#include "gpe.h" -#elif defined(HWMACRO_STD) -#include "std.h" -#elif defined(HWMACRO_PPE) -#include "ppe.h" -#else -#error "Macro Type not specified. Are you building from the correct directory?" -#endif - - -#include "ppe42_asm.h" -#include "ppe42_gcc.h" -#include "ppe42_spr.h" -#include "ppe42_msr.h" - - -///start - -/// 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. - - -// 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 ("sync" : : : "memory") - -/// Memory barrier -#define sync() asm volatile ("sync" : : : "memory") - -/// Instruction barrier -#define isync() asm volatile ("sync" : : : "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);} while(0) - -/// 8-bit MMIO Read -#define in8(addr) \ -({uint8_t __data = *(volatile uint8_t *)(addr); __data;}) - -/// 16-bit MMIO Write -#define out16(addr, data) \ -do {*(volatile uint16_t *)(addr) = (data);} while(0) - -/// 16-bit MMIO Read -#define in16(addr) \ -({uint16_t __data = *(volatile uint16_t *)(addr); __data;}) - -/// 32-bit MMIO Write -#define out32(addr, data) \ -do {*(volatile uint32_t *)(addr) = (data);} while(0) - -/// 32-bit MMIO Read -#define in32(addr) \ -({uint32_t __data = *(volatile uint32_t *)(addr); __data;}) - -#ifdef HWMACRO_GPE - -/// 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); \ - *__addr_lo = (__data & 0xffffffff); \ - } while(0) - -#else /* standard PPE's require a 64 bit write */ - -/// 64-bit MMIO Write -#define out64(addr, data) \ -{\ - uint64_t __d = (data); \ - uint32_t* __a = (uint32_t*)(addr); \ - asm volatile \ - (\ - "stvd %1, %0 \n" \ - : "=o"(*__a) \ - : "r"(__d) \ - ); \ -} - -#endif /* HWMACRO_GPE */ - -#ifdef HWMACRO_GPE -/// 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; \ - __data = (__data << 32) | *__addr_lo; \ - __data;}) - -#else /* Standard PPE's require a 64 bit read */ - -#define in64(addr) \ -({\ - uint64_t __d; \ - uint32_t* __a = (uint32_t*)(addr); \ - asm volatile \ - (\ - "lvd %0, %1 \n" \ - :"=r"(__d) \ - :"o"(*__a) \ - ); \ - __d; \ -}) - -#endif /* HWMACRO_GPE */ - -#endif /* __ASSEMBLER__ */ - -#include "ppe42_irq.h" - -#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__ - - - -#include "ppe42_context.h" - -// PPE42 stack characteristics for PK. The pre-pattern pattern is selected -// to be easily recognizable yet be an illegal instruction. - -#define PK_STACK_DIRECTION -1 -#define PK_STACK_PRE_DECREMENT 1 -#define PK_STACK_ALIGNMENT 8 -#define PK_STACK_TYPE unsigned int -#define PK_STACK_PATTERN 0x03abcdef - -// Kernel data structure offsets for assembler code - -#define PK_THREAD_OFFSET_SAVED_STACK_POINTER 0 -#define PK_THREAD_OFFSET_STACK_LIMIT 4 -#define PK_THREAD_OFFSET_STACK_BASE 8 - -// PK boot loader panic codes - -#define PPE42_BOOT_VECTORS_NOT_ALIGNED 0x00405001 - -// Interrupt handler panic codes - -#define PPE42_DEFAULT_IRQ_HANDLER 0x00405010 -#define PPE42_DEFAULT_SPECIAL_HANDLER 0x00405011 -#define PPE42_PHANTOM_INTERRUPT 0x00405012 -#define PPE42_PROGRAM_HALT 0x00405013 - - -// Exception handling invariant panic codes - -#define PPE42_IRQ_FULL_EXIT_INVARIANT 0x00405020 -#define PPE42_IRQ_FAST2FULL_INVARIANT 0x00405021 - - -// API error panic codes - - -// 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 external and machine check exceptions. This -/// definition can be overriden by the application. - -#ifndef PK_THREAD_MACHINE_CONTEXT_DEFAULT -#define PK_THREAD_MACHINE_CONTEXT_DEFAULT \ - (MSR_UIE | MSR_EE | MSR_ME) - -#endif - - -#ifndef __ASSEMBLER__ - -/// The PK 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 PK_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 -/// __pk_panic_save_dbcr0 and __pk_panic_save_r3 defined in ppe42_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 PK_PANIC - -/*#define PK_PANIC(code) \ - do { \ - barrier(); \ - asm volatile ("stw %r3, __pk_panic_save_r3@sda21(0)"); \ - asm volatile ("mfdbcr0 %r3"); \ - asm volatile ("stw %r3, __pk_panic_save_dbcr0@sda21(0)"); \ - asm volatile ("lwz %r3, __pk_panic_dbcr0@sda21(0)"); \ - asm volatile ("mtdbcr0 %r3"); \ - asm volatile ("isync"); \ - asm volatile ("lwz %r3, __pk_panic_save_r3@sda21(0)"); \ - asm volatile ("rlwimi 1,1,0,0,0"); \ - asm volatile ("trap"); \ - asm volatile (".long %0" : : "i" (code)); \ - } while (0) -*/ -#define PK_PANIC(code) \ - do { \ - barrier(); \ - asm volatile ("b ."); \ - } while (0) - -// These variables are used by the PK_PANIC() definition above to save and -// restore state. __pk_panic_dbcr0 is the value loaded into DBCR0 to force -// traps to halt the OCC and freeze the timers. - -//#ifdef __PPE42_CORE_C__ -//uint32_t __pk_panic_save_r3; -//uint32_t __pk_panic_save_dbcr0; -//uint32_t __pk_panic_dbcr0 = DBCR0_EDM | DBCR0_TDE | DBCR0_FT; -//#endif - -#endif // PK_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 PK 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 PK_PANIC - -#define PK_PANIC(code) _pk_panic code - - .macro _pk_panic, code - b . - .endm - -#endif // PK_PANIC - -#endif // __ASSEMBLER__ - - -// Application-overridible definitions for the PK 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 PPE42_DBCR_INITIAL -#define PPE42_DBCR_INITIAL DBCR_TRAP -#endif - -/// This is the value of the MSR used during initialization. Once PK threads -/// are started (with \c pk_start_threads()), all machine contexts derive -/// from the default thread context \c -/// PK_THREAD_MACHINE_CONTEXT_DEFAULT. This definition can be overriden by -/// the application. -/// -/// The default is to enable machine checks only. - -#ifndef PPE42_MSR_INITIAL -#define PPE42_MSR_INITIAL MSR_ME -#endif - -/// The \a argc argument passed to \c main(). This definition can be overriden -/// by the application. - -#ifndef PPE42_ARGC_INITIAL -#define PPE42_ARGC_INITIAL 0 -#endif - -/// The \a argv argument passed to \c main(). This definition can be overriden -/// by the application. - -#ifndef PPE42_ARGV_INITIAL -#define PPE42_ARGV_INITIAL 0 -#endif - -/// Optionally trap the reset for the debugger, which means that the PPE42 -/// 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 PPE42_RESET_TRAP -#define PPE42_RESET_TRAP 0 -#endif - -#ifndef __ASSEMBLER__ - -/// The PPE42 PK machine context is simply the MSR, a 32-bit integer. - -typedef uint32_t PkMachineContext; - -/// Disable interrupts and return the current -/// context. -/// -/// \param context A pointer to an PkMachineContext, this is the context that -/// existed before interrupts were disabled. Typically this -/// context is restored at the end of a critical section. -/// -/// Return values other then PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_ARGUMENT_INTERRUPT An illegal priority was specified. - -UNLESS__PPE42_CORE_C__(extern) -inline int -pk_interrupt_disable(PkMachineContext *context) -{ - *context = mfmsr(); - - wrteei(0); - - return PK_OK; -} - -/// Set the machine context. -/// -/// \param context A pointer to an PkMachineContext -/// -/// Return values other then PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_ARGUMENT_CONTEXT_SET A null pointer was provided as -/// the \a context argument or an illegal machine context was specified. - -UNLESS__PPE42_CORE_C__(extern) -inline int -pk_machine_context_set(PkMachineContext *context) -{ - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(context == 0, PK_INVALID_ARGUMENT_CONTEXT_SET); - } - - mtmsr(*context); - - return PK_OK; -} - -/// Get the machine context. -/// -/// \param context A pointer to an PkMachineContext. -/// -/// Return values other then PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_ARGUMENT_CONTEXT_GET A null pointer was provided as -/// the \a context argument. - -UNLESS__PPE42_CORE_C__(extern) -inline int -pk_machine_context_get(PkMachineContext *context) -{ - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(context == 0, PK_INVALID_ARGUMENT_CONTEXT_GET); - } - - *context = mfmsr(); - - return PK_OK; -} - -extern void __ctx_switch(); -/// The PK context switch for the PPE kernel -// There is no protected mode in PPE42 so just call kernel code -#define __pk_switch() __ctx_switch() - - -/// 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 -__pk_stack_create_initial_frame(PkAddress *stack, size_t *size) \ -{ - *stack -= 8; - *size -= 8; - *((PK_STACK_TYPE *)(*stack)) = 0; -} - -/// The PK Kernel Context for PPE42 -/// -/// The PK portable kernel does not define how the kernel keeps track of -/// whether PK is running, interrupt levels, and other debug -/// information. Instead it defines an API that the port must provide to the -/// portable kernel. -/// -/// In the PPE42 port, the kernel context is maintained in SPRG0. This -/// 32-bit value is treated as 6 distinct fields as indicated in the structure -/// definition. -typedef union { - - uint32_t value; - - struct { - - /// A flag indicating that PK is in thread mode after a call of - /// pk_start_threads(). - unsigned thread_mode : 1; - - /// If this field is non-zero then PK is processing an interrupt - /// and the \c irq field will contain the PkIrqId of the interrupt - /// that kicked off interrupt processing. - unsigned processing_interrupt : 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 : 6; - - /// This bit tracks whether the current context can be discarded or - /// if the context must be saved. If the processor takes an interrupt - /// and this bit is set, then the current context will be discarded. - /// This bit is set at the end of handling an interrupt and prior - /// to entering the wait enabled state. - unsigned discard_ctx : 1; - - /// The PkIrqId of the currently running (or last run) handler. If - /// \c processing_interrupt is set, then this is the - /// PkIrqId of the IRQ that is currently executing. - unsigned irq : 7; - - /// Each PPE application will define (or not) the interpretation of - /// this field. Since SPRG0 is saved and restored during during thread - /// context switches, this field can be used to record the progress of - /// individual threads. The kernel and/or application will provide - /// APIs or macros to read and write this field. - unsigned app_specific : 16; - - } fields; - -} __PkKernelContext; - -// These APIs are provided for applications to get and set the app_specific -// field of the kernel context which is held in sprg0. - -static inline uint16_t ppe42_app_ctx_get(void) -{ - __PkKernelContext __ctx; - __ctx.value = mfspr(SPRN_SPRG0); - return __ctx.fields.app_specific; -} - -static inline void ppe42_app_ctx_set(uint16_t app_ctx) -{ - PkMachineContext mctx; - __PkKernelContext __ctx; - mctx = mfmsr(); - wrteei(0); - __ctx.value = mfspr(SPRN_SPRG0); - __ctx.fields.app_specific = app_ctx; - mtspr(SPRN_SPRG0, __ctx.value); - mtmsr(mctx); -} - -// These APIs are provided to the PK portable kernel by the port. - -/// PK threads have been started by a call of pk_start_threads(). - -#define __pk_kernel_mode_thread() \ - ({ \ - __PkKernelContext __ctx; \ - __ctx.value = mfspr(SPRN_SPRG0); \ - __ctx.fields.thread_mode;}) - - -/// PK is executing in a thread context (not an interrupt handler). - -#define __pk_kernel_context_thread() \ - ({ \ - __PkKernelContext __ctx; \ - __ctx.value = mfspr(SPRN_SPRG0); \ - __ctx.fields.thread_mode && !__ctx.fields.processing_interrupt;}) - - -/// PK is executing an interrupt handler of any priority. - -#define __pk_kernel_context_any_interrupt() \ - ({ \ - __PkKernelContext __ctx; \ - __ctx.value = mfspr(SPRN_SPRG0); \ - __ctx.fields.processing_interrupt;}) - - -// PK requires the port to define the type PkThreadQueue, which is a -// priority queue (where 0 is the highest priority). This queue must be able -// to handle PK_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 PK_THREADS if -// the queue is empty (or a queue could be initialized with that entry always -// present - PK 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 PPE42 with 32 threads (implied), this is a job for a uint32_t and -// cntlzw(). - -static inline void -__pk_thread_queue_clear(volatile PkThreadQueue *queue) -{ - *queue = 0; -} - -static inline void -__pk_thread_queue_insert(volatile PkThreadQueue *queue, PkThreadPriority priority) -{ - *queue |= (0x80000000u >> priority); -} - -static inline void -__pk_thread_queue_delete(volatile PkThreadQueue *queue, PkThreadPriority priority) -{ - *queue &= ~(0x80000000u >> priority); -} - -static inline PkThreadPriority -__pk_thread_queue_min(volatile PkThreadQueue *queue) -{ - return cntlzw(*queue); -} - -static inline int -__pk_thread_queue_member(volatile PkThreadQueue *queue, PkThreadPriority priority) -{ - return ((*queue >> (31 - priority)) & 1); -} - -static inline void -__pk_thread_queue_union(volatile PkThreadQueue *queue0, - volatile PkThreadQueue *queue1) -{ - *queue0 |= *queue1; -} - -static inline int -__pk_thread_queue_count(volatile PkThreadQueue* queue) -{ - return __builtin_popcount(*queue); -} - - -/// This macro is used to call __pk_start_threads() using the kernel stack, -/// in a critical section. - -#define __pk_call_pk_start_threads() \ - do { \ - PkMachineContext ctx; \ - pk_critical_section_enter(&ctx); \ - asm volatile ("mr 1, %0; mtlr %1; blrl" : : \ - "r" (__pk_kernel_stack), \ - "r" (__pk_start_threads)); \ - PK_PANIC(PK_START_THREADS_RETURNED); \ - } while (0) - - -#endif /* __ASSEMBLER__ */ - -/// The __PkKernelContext 'thread_mode' bit as a flag - -#define PPE42_THREAD_MODE 0x8000 -#define PPE42_PROC_IRQ 0x4000 -#define PPE42_DISCARD_CTX 0x0080 - -#define PPE42_THREAD_MODE_BIT 0 -#define PPE42_PROC_IRQ_BIT 1 -#define PPE42_DISCARD_CTX_BIT 8 - -#ifndef __ASSEMBLER__ - -/// Code breakpoints for PPE42 -/// -/// This macro inserts a special PPE42-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 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 PPE42 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) { \ - PkMachineContext __ctx; \ - pk_critical_section_enter(&__ctx); \ - _code_breakpoint_prologue(); \ - _code_breakpoint_epilogue(); \ - pk_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 /* __PPE42_H__ */ diff --git a/pk/ppe42/ppe42_asm.h b/pk/ppe42/ppe42_asm.h deleted file mode 100644 index dd586706..00000000 --- a/pk/ppe42/ppe42_asm.h +++ /dev/null @@ -1,608 +0,0 @@ -#ifndef __PPE42_ASM_H__ -#define __PPE42_ASM_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42_asm.h -/// \brief Generic assembler macros for 32-bit PPE42 - -// 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 ppe42_asm Generic assembler macros for 32-bit PPE42 -/// -/// -/// \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 - -### *************************************************************************** -### 64-bit macros -### *************************************************************************** - -### *************************************************************************** -### Using symbols for register names makes the code more readable and allows -### us to do register arithmetic within macros. -### *************************************************************************** - -.equiv r0, 0 -.equiv r1, 1 -.equiv sp, 1 -.equiv r3, 3 -.equiv r4, 4 -.equiv r5, 5 -.equiv r6, 6 -.equiv r7, 7 -.equiv r8, 8 -.equiv r9, 9 -.equiv r10, 10 - -.equiv r28, 28 -.equiv r29, 29 -.equiv r30, 30 -.equiv r31, 31 - -.equiv d3, 3 -.equiv d4, 4 -.equiv d5, 5 -.equiv d6, 6 -.equiv d7, 7 -.equiv d8, 8 -.equiv d9, 9 -.equiv d10, 10 -.equiv d28, 28 -.equiv d29, 29 -.equiv d30, 30 -.equiv d31, 31 - -### *************************************************************************** -### Load virtual doubleword generic. Load a virtual doubleword from a relocatable -### address expression. If the optional RA is specified, the address remains in -### RA. -### *************************************************************************** -.macro _lvdg DT:req addr:req RA=-1 - .if \RA == -1 - lis \DT, (\addr)@ha - lvd \DT, (\addr)@l(\DT) - .else - lis \RA, (\addr)@ha - lvdu \DT, (\addr)@l(\RA) - .endif -.endm - -### *************************************************************************** -### Load virtual doubleword from a relocatable small data area address -### *************************************************************************** -.macro _lvdsd DT:req addr:req - lvd \DT, (\addr)@sda21(0) -.endm - -### *************************************************************************** -### Store virtual doubleword generic. Store a virtual doubleword based on a -### relocatable address expression. The address remains in RA. -### *************************************************************************** -.macro _stvdg DS:req addr:req RA:req - lis \RA, (\addr)@ha - stvdu \DS, (\addr)@l(\RA) -.endm - -### *************************************************************************** -### Store virtual doubleword to a relocatable small data address expression -### *************************************************************************** -.macro _stvdsd DS:req addr:req - stvd \DS, (\addr)@sda21(0) -.endm - -### *************************************************************************** -### Load virtual doubleword absolute. Set DT to an absolute 64-bit constant -### *************************************************************************** -.macro _lvda DT, cvalue - lwa (\DT + 1)%32, (\cvalue) & 0x00000000ffffffff - lwa \DT, (\cvalue) >> 32 -.endm - -### *************************************************************************** -### -### 64-bit arithmetic macros -### -### *************************************************************************** - -.macro check_overlap2 DA, DB - .if ((\DA - \DB) % 32) == 1 || ((\DA - \DB) % 32) == -1 - .error "virtual doubleword registers must be identical or non-overlapping" - .endif -.endm - -.macro check_overlap3 DA, DB, DC - check_overlap2 \DA, \DB - check_overlap2 \DA, \DC - check_overlap2 \DB, \DC -.endm - -### *************************************************************************** -### Add virtual doubleword carrying -### *************************************************************************** -.macro _addvdc DT, DA, DB - check_overlap3 \DT, \DA, \DB - addc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 - adde \DT, \DA, \DB -.endm - -### *************************************************************************** -### Add virtual doubleword to signed 16-bit immediate carrying -### *************************************************************************** -.macro _addvdic DT, DA, SI - .if \DA == 31 - .error "d31 for addend register is not supported" - .endif - check_overlap2 \DT, \DA - addi (\DT+1)%32, \DA+1, SI - addze \DT, \DA -.endm - -### *************************************************************************** -### Add virtual doubleword to unsigned word carrying -### *************************************************************************** -.macro _addvdwuc DT, DA, RB - check_overlap2 \DT, \DA - addc (\DT+1)%32, (\DA+1)%32, \RB - addze \DT, \DA -.endm - -### *************************************************************************** -### Subtract virtual doubleword carrying -### *************************************************************************** -.macro _subvdc DT, DA, DB - check_overlap3 \DT, \DA, \DB - subfc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 - subfe \DT, \DA, \DB -.endm - -### *************************************************************************** -### -### 64-bit logic macros -### -### *************************************************************************** - -### *************************************************************************** -### AND virtual doubleword -### *************************************************************************** -.macro _andvd DT, DA, DB - check_overlap3 \DT, \DA, \DB - and (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 - and \DT, \DA, \DB -.endm - -### *************************************************************************** -### ANDC virtual doubleword -### *************************************************************************** -.macro _andcvd DT, DA, DB - check_overlap3 \DT, \DA, \DB - andc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 - andc \DT, \DA, \DB -.endm - -### *************************************************************************** -### EQV virtual doubleword -### *************************************************************************** -.macro _eqvvd DT, DA, DB - check_overlap3 \DT, \DA, \DB - eqv (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 - eqv \DT, \DA, \DB -.endm - -### *************************************************************************** -### OR virtual doubleword -### *************************************************************************** -.macro _orvd DT, DA, DB - check_overlap3 \DT, \DA, \DB - or (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 - or \DT, \DA, \DB -.endm - -### *************************************************************************** -### ORC virtual doubleword -### *************************************************************************** -.macro _orcvd DT, DA, DB - check_overlap3 \DT, \DA, \DB - orc (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 - orc \DT, \DA, \DB -.endm - -### *************************************************************************** -### XOR virtual doubleword -### *************************************************************************** -.macro _xorvd DT, DA, DB - check_overlap3 \DT, \DA, \DB - xor (\DT+1)%32, (\DA+1)%32, (\DB+1)%32 - xor \DT, \DA, \DB -.endm - -#endif /* __ASSEMBLER__ */ - -/// \endcond - -// Local Variables: -// mode:asm -// End: - -#endif /* __PPE42_ASM_H__ */ diff --git a/pk/ppe42/ppe42_boot.S b/pk/ppe42/ppe42_boot.S deleted file mode 100644 index 32fdfd3a..00000000 --- a/pk/ppe42/ppe42_boot.S +++ /dev/null @@ -1,169 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42_boot.S -/// \brief PK bootloader for PPE42 - - .nolist -#include "pk.h" - .list - -### PK Bootloader for PPE42 -### -### 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 PK 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 -### DCWR - Data cache write-through disabled -### ESR - No exception syndromes -### MSR - No exceptions/interrupts are allowed -### -### 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 __pk_boot - .global __reset_trap - -__pk_boot: - - ## Trap the reset for the debugger. Set R0 to a non-zero value in the - ## debugger to continue. - - .if PPE42_RESET_TRAP - li %r0, 0 -__reset_trap: - cmpwi %r0, 0 - beq __reset_trap - .endif - - ## Set up PowerPC EABI constant registers. These registers are never - ## again touched by the PK 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. - - li %r3, 0 - mttcr %r3 - - ## 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, _PK_INITIAL_STACK - _clrfield %r1, %r1, 3, 29 # 8-byte align - li %r3, 0 - stwu %r3, -8(%r1) - - ## SPRG0 (__PkKernelContext) is initialized to 0 - ## indicating that the PK kernel is not in thread mode, and no - ## interrupts are active. - - li %r3, 0 - mtsprg0 %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 PPE42. - -#ifndef NO_INIT_DBCR0 - _liwa %r3, PPE42_DBCR_INITIAL - mtdbcr %r3 -#endif - - ## The exception vector prefix is set - it must be 512 byte aligned. - ## NOTE: for PPE42, the IVPR is read only, but can be changed through scoms - - #_liw %r3, __vectors - #andi. %r4, %r3, 0x01ff - #beq 1f - #_pk_panic PPE42_BOOT_VECTORS_NOT_ALIGNED -#1: - #mtivpr %r3 - #sync - - ## The MSR to be used during the rest of intialization is - ## established. This MSR should NOT enable - ## interrupts, but could enable machine check exceptions. - - _liwa %r3, PPE42_MSR_INITIAL - mtmsr %r3 - sync - -#ifdef PK_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 PK - ## 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, __pk_ram_lma - 4 # src - liw %r4, __pk_ram_vma - 4 # dest - liw %r5, __pk_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 /* PK_BOOT_FROM_ROM */ - - - ## Call the system setup code. - - bl __ppe42_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, PPE42_ARGC_INITIAL - _liw %r4, PPE42_ARGV_INITIAL - bl __pk_main - - b __pk_idle_thread_from_bootloader - - .epilogue __pk_boot - diff --git a/pk/ppe42/ppe42_cache.h b/pk/ppe42/ppe42_cache.h deleted file mode 100644 index 01031b41..00000000 --- a/pk/ppe42/ppe42_cache.h +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef __PPE42_CACHE_H__ -#define __PPE42_CACHE_H__ - -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42_cache.h -/// \brief PowerPC-lite (PPE) cache management header for PK -/// -/// 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") - -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 /* __PPE42_CAHE_H__ */ diff --git a/pk/ppe42/ppe42_context.h b/pk/ppe42/ppe42_context.h deleted file mode 100644 index 2412565b..00000000 --- a/pk/ppe42/ppe42_context.h +++ /dev/null @@ -1,201 +0,0 @@ -#ifndef __PPE42_CONTEXT_H__ -#define __PPE42_CONTEXT_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42_context.h -/// \brief PPE42 Machine and Thread context for PK - -/// \page ppe42_machine_context PPE42 Assembler Macros for PK Machine -/// Context (Critical Sections) -/// -/// \section _pk_enter_critical \b _pk_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 ctxreg A register that will hold (holds) the machine context (MSR) -/// prior to entering the critical section (to be restored) for \c -/// _pk_critical_section_enter (\c _pk_critical_section_exit). -/// -/// \arg \c scrreg A scratch register required for the computation of -/// \c _pk_critical_section_enter. -/// -/// Forms: -/// -/// \b _pk_critical_section_enter \a priority, \a ctxreg, \a scrreg - Enter a -/// critical section \n -/// \b _pk_critical_section_exit \a ctxreg - Exit a critical section - -#ifdef __ASSEMBLER__ - - .set _msr_ee_bit, MSR_EE_BIT - - .macro _pk_critical_section_enter ctxreg, scrreg - mfmsr \ctxreg - wrteei 0 - .endm - - .macro _pk_critical_section_exit ctxreg - mtmsr \ctxreg - .endm - -// **************************************************************************** -// PK context save/restore macros for 32-bit Embedded PowerPC -// **************************************************************************** - -// All stack frames are 8-byte aligned in conformance with the EABI. PK -// 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. - -// USPRG0 holds the __PkKernelContext structure (defined in ppe42.h) that -// represents the current kernel context. The layout is as follows: -// -// Bits Meaning -// ============== -// 0 The 'thread_mode' flag -// 1 The 'processing_interrupt" flag -// 2:7 The thread priority of the running thread -// 8 The 'discard_ctx' flag -// 9:15 The IRQ currently being processed -// 16:31 The application specific data -// -// When PK is initialized USPRG0 is initialized to 0. When thread-mode is -// entered (by pk_start_threads()) bit 0 is set to 1. If desired, -// once initialized (with pk_initialize()) PK can simply -// handle interrupts, reverting back to the non-thread-mode idle loop when -// there's nothing to do. -// - - ## ------------------------------------------------------------ - ## Unused registers for embedded PPE42` - ## ------------------------------------------------------------ - - ## 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 - - ## ------------------------------------------------------------ - ## The PK context layout for Embedded PPE42 - ## ------------------------------------------------------------ - - .set PK_CTX_GPR1, 0x00 # Dedicated; Stack pointer - .set PK_CTX_LINKAGE, 0x04 # Slot for handler to store LR - .set PK_CTX_GPR3, 0x08 # Volatile; Parameter; Return Value - .set PK_CTX_GPR4, 0x0c # Volatile; Parameter - .set PK_CTX_GPR5, 0x10 # Volatile; Parameter - .set PK_CTX_GPR6, 0x14 # Volatile; Parameter - .set PK_CTX_CR, 0x18 # Condition register - .set PK_CTX_LR, 0x1c # Link register - - .set PK_CTX_GPR7, 0x20 # Volatile; Parameter - .set PK_CTX_GPR8, 0x24 # Volatile; Parameter - .set PK_CTX_GPR9, 0x28 # Volatile; Parameter - .set PK_CTX_GPR10, 0x2c # Volatile; Parameter - .set PK_CTX_GPR28, 0x30 # Non-volatile - .set PK_CTX_GPR29, 0x34 # Non-volatile - .set PK_CTX_GPR30, 0x38 # Non-volatile - .set PK_CTX_GPR31, 0x3c # Non-volatile - - .set PK_CTX_XER, 0x40 # Fixed-point exception register - .set PK_CTX_CTR, 0x44 # Count register - .set PK_CTX_SRR0, 0x48 # Save/restore register 0 - .set PK_CTX_SRR1, 0x4c # Save/restore register 1 - .set PK_CTX_GPR0, 0x50 # Volatile; Language specific - .set PK_CTX_KERNEL_CTX, 0x54 # Saved __PkKernelContext for IRQ - - .set PK_CTX_SIZE, 0x58 # Must be 8-byte aligned - - ## ------------------------------------------------------------ - ## Push the interrupted context if necessary - ## - ## This macro saves off some context in preparation for calling - ## the pk_ctx_check_discard routine. This is an attempt to use - ## the 32 byte cache more efficiently. - ## - ## 8 Instructions - ## ------------------------------------------------------------ - ## - - .macro _pk_ctx_push_as_needed branch_addr:req - - stwu %r1, -PK_CTX_SIZE(%r1) - stvd %d3, PK_CTX_GPR3(%r1) - mfcr %r3 - mflr %r4 - stvd %d3, PK_CTX_CR(%r1) - _liw %r3, \branch_addr - b ctx_check_discard - .endm - - - ## ------------------------------------------------------------ - ## update the kernel context in response to an interrupt. - ## ------------------------------------------------------------ - - ## The kernel context is updated with the currently active - ## IRQ in bits 9:15. - - .macro _update_kernel_context irqreg, ctxreg - rlwimi \ctxreg, \irqreg, 16, 9, 15 //set the irq # - oris \ctxreg, \ctxreg, 0x4000 //set the 'processing_interrupt' flag - mtsprg0 \ctxreg - -#if PK_KERNEL_TRACE_ENABLE - mr %r31, \irqreg - srwi \ctxreg, \ctxreg, 16 - PK_KERN_TRACE_ASM16("INTERRUPT_CONTEXT(0x%04x)", \ctxreg) - mr \irqreg, %r31 -#endif - - .endm - -#else /* __ASSEMBLER__ */ - -/// PK 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; - uint32_t linkage; - uint32_t r3; - uint32_t r4; - uint32_t r5; - uint32_t r6; - uint32_t cr; - uint32_t lr; - - uint32_t r7; - uint32_t r8; - uint32_t r9; - uint32_t r10; - uint32_t r28; - uint32_t r29; - uint32_t r30; - uint32_t r31; - - uint32_t xer; - uint32_t ctr; - uint32_t srr0; - uint32_t srr1; - uint32_t r0; - uint32_t sprg0; - -} PkThreadContext; - - -#endif /* __ASSEMBLER__ */ - -#endif /* __PPE42_CONTEXT_H__ */ - - diff --git a/pk/ppe42/ppe42_core.c b/pk/ppe42/ppe42_core.c deleted file mode 100644 index 2fa86e68..00000000 --- a/pk/ppe42/ppe42_core.c +++ /dev/null @@ -1,126 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42_core.c -/// \brief The final bits of PK runtime code required to complete the PPE42 -/// port. -/// -/// The entry points in this file are considered 'core' routines that will -/// always be present during runtime in any PK application. - -#define __PPE42_CORE_C__ - -#include "pk.h" - -typedef union -{ - uint64_t value; - struct - { - uint32_t dec_start; - uint32_t dec_change_tag; - }; -}ppe42_timebase_data_t; - -ppe42_timebase_data_t ppe42_tb_data = {0}; -PkTimebase ppe42_64bit_timebase = 0; - - -#if PK_TIMER_SUPPORT - -// The tickless kernel timer mechanism for PPE42 -// -// This routine must be called from a 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 - PK 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 -// __pk_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 PK specification. - -#ifndef APPCFG_USE_EXT_TIMEBASE -void -__pk_schedule_hardware_timeout(PkTimebase timeout) -{ - PkTimebase now; - uint32_t new_dec; - uint32_t dec; - - if (timeout != PK_TIMEBASE_MAX) { - - now = pk_timebase_get(); - - if (timeout <= now) { - new_dec = 1; - } else if ((timeout - now) > 0xffff0000) { - new_dec = 0xffff0000; - } else { - new_dec = timeout - now; - } - - //read and write the DEC back-to-back so that we lose as little time - //as possible - dec = mfspr(SPRN_DEC); - mtspr(SPRN_DEC, new_dec); - - //update our 64bit accumulator with how much time has advanced since - //we last changed it. - ppe42_64bit_timebase += ppe42_tb_data.dec_start - dec; - - //update our start time so we know how much time has advanced since - //this update of the accumulator - ppe42_tb_data.dec_start = new_dec; - ppe42_tb_data.dec_change_tag++; - } -} - -#else - -void -__pk_schedule_hardware_timeout(PkTimebase timeout) -{ - PkTimebase now; - PkTimebase diff; - uint32_t new_dec; - - if (timeout != PK_TIMEBASE_MAX) { - - now = pk_timebase_get(); - - //update our 64bit accumulator with the current snapshot - ppe42_64bit_timebase = now; - - if (timeout <= now) - { - new_dec = 1; - } - else - { - diff = (timeout - now); - - if (diff > 0xfffffffful) - { - new_dec = 0xffffffff; - } - else - { - new_dec = diff; - } - } - - mtspr(SPRN_DEC, new_dec); - - } -} - -#endif /* APPCFG_USE_EXT_TIMEBASE */ - -#endif /* PK_TIMER_SUPPORT */ - -#undef __PPE42_CORE_C__ diff --git a/pk/ppe42/ppe42_exceptions.S b/pk/ppe42/ppe42_exceptions.S deleted file mode 100644 index f8f68d99..00000000 --- a/pk/ppe42/ppe42_exceptions.S +++ /dev/null @@ -1,501 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42_exceptions.S -/// \brief PPE42 exception vector area. -/// -/// \cond - - .nolist -#include "pk.h" - .list - -## declare and initializes global variables that hold external irq config data -## Each PPE macro type (GPE, CME, and SBE) will have it's own implementation of this macro -## defined in (gpe, cme, sbe)_common.h - .hwmacro_irq_cfg_bitmaps - -### **************************************************************************** -### .vectors - This section contains all ppe42 exception vectors -### -### **************************************************************************** - - .section .vectors, "ax", @progbits - - .global __vectors - -__vectors: - - ############################################################ - # 0x0000 : Machine Check - ############################################################ - - ### Unmaskable interrupts (including program interrupts) are promoted - ### to machine check interrupts if MSR[UIE] = 0 and MSR[ME] = 1. - ### If the machine check was caused by a program interrupt it - ### will be forwarded to the program exception handler. -__machine_check: - - PPE42_MACHINE_CHECK_HANDLER - - ############################################################ - # 0x0040 : System Reset - ############################################################ - .global __system_reset - .org __vectors + 0x0040 -__system_reset: - b __pk_boot - - ############################################################ - # 0x0060 : Data Storage Interrupt - ############################################################ - - .org __vectors + 0x0060 -__data_storage: - - PPE42_DATA_STORAGE_HANDLER - - ############################################################ - # 0x0080 : Instruction Storage Interrupt - ############################################################ - - .org __vectors + 0x0080 -__instruction_storage: - - PPE42_INSTRUCTION_STORAGE_HANDLER - - - ############################################################ - # 0x00A0 : External Interrupt - ############################################################ - - .org __vectors + 0x00A0 -__external_interrupt_vector: - _pk_ctx_push_as_needed __get_ext_irq - - ############################################################ - # 0x00C0 : Alignment Exception - ############################################################ - - .org __vectors + 0x00C0 -__alignment_exception: - - PPE42_ALIGNMENT_HANDLER - - - ############################################################ - # 0x00E0 : Program Interrupt - ############################################################ - - .org __vectors + 0x00E0 - - ### Program exceptions are utilized for emulating the system call - ### instruction (0x44000002) which is used for doing context - ### switches between threads. They can also be used by the code - ### to signal an exception in an error scenario. -__program_exception: - _pk_ctx_push_as_needed program_exception_handler - - - ############################################################ - # 0x0100 : DEC Interrupts - ############################################################ - - .org __vectors + 0x0100 -__dec_interrupt: - _pk_ctx_push_as_needed dec_handler - - ############################################################ - # 0x0120 : FIT Interrupts - ############################################################ - .org __vectors + 0x0120 -__fit_interrupt: - - _pk_ctx_push_as_needed fit_handler - - ############################################################ - # 0x0140 : Watchdog Interrupts - ############################################################ - .org __vectors + 0x0140 -__watchdog_interrupt: - - _pk_ctx_push_as_needed watchdog_handler - - -### **************************************************************************** -### The rest of the code in this file doesn't have to be placed anywhere -### special, so just place it in the .text section. -### **************************************************************************** - - .section .text, "ax", @progbits - - - ## The idle thread has no permanent register context. The idle thread - ## entry point is re-entered whenever the idle thread is scheduled. - - .global __pk_idle_thread - .global __pk_idle_thread_from_bootloader - -__pk_idle_thread: - - ## The idle thread 'uses' the kernel 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 interrupts disabled. - ## - ## The kernel context is initialized to indicate that the idle thread - ## is running - the idle thread priority is PK_THREADS, the - ## 'thread-mode' bit is asserted and so is the 'discard-ctx" bit. - ## In addition, the previous kernel context is stored in the lower - ## 16 bits. - ## - ## This loop can also be called from the PK bootloader if main() - ## returns - in which case we don't muck with the SPRG0 or the stack - ## pointer. - mfsprg0 %r3 - srwi %r3, %r3, 16 - oris %r3, %r3, (PK_THREADS << 8) | PPE42_THREAD_MODE | PPE42_DISCARD_CTX - mtsprg0 %r3 - _lwzsd %r1, __pk_kernel_stack - -__pk_idle_thread_from_bootloader: - - PK_KERN_TRACE_ASM16("ENTER_IDLE_STATE") - - _lwzsd %r3, __pk_thread_machine_context_default - _oriwa %r3, %r3, MSR_WE - mtmsr %r3 - b . - - ## pk_halt() is implemented on the ppe42 by writing a value of 0x3 to - ## the RST field of the DBCR. - .global pk_halt -pk_halt: - lis %r31, 0x3000 - mtdbcr %r31 - .long 0 - - -dec_handler: - - ## The portable timer handler of PK is a full-mode handler with the prototype: - ## void (*pk_timer_handler)(void). - ## - ## To support the portable specification, the kernel clears the - ## interrupt by writing the DIS back into the TSR before calling the - ## handler. The timer handler does not take any arguments. - - li %r4, PPE42_IRQ_DEC - _update_kernel_context %r4, %r3 - - _liwa %r3, TSR_DIS - mttsr %r3 - - bl __pk_timer_handler - b check_for_ext_interrupt - -program_exception_handler: - _pk_panic PPE42_ILLEGAL_INSTRUCTION - - .global __pk_next_thread_resume -__pk_next_thread_resume: - - _lwzsd %r3, __pk_next_thread - _stwsd %r3, __pk_current_thread - - ## Enter the wait enabled state if the thread pointer is null - bwz %r3, __pk_idle_thread - - ## switch to the new thread stack - lwz %r1, PK_THREAD_OFFSET_SAVED_STACK_POINTER(%r3) - - ## load sprg0 from the stack and update the thread priority - ## in case it changed. -restore_and_update_sprg0: - _lbzsd %r31, __pk_next_priority - - PK_KERN_TRACE_ASM16("RESUME_THREAD(%d)", %r31) - - lwz %r3, PK_CTX_KERNEL_CTX(%r1) - rlwimi %r3, %r31, 24, 2, 7 - mtsprg0 %r3 - - b ctx_pop - -fit_handler: - - ## The FIT handler is user defined. By - ## convention the kernel clears the interrupt by writing the FIS back - ## into the TSR. - - li %r4, PPE42_IRQ_FIT - - _update_kernel_context %r4, %r3 - - _lwzsd %r3, __ppe42_fit_arg - - _liwa %r6, TSR_FIS - mttsr %r6 - - _lwzsd %r6, __ppe42_fit_routine - mtlr %r6 - blrl - - b check_for_ext_interrupt - -watchdog_handler: - ## Watchdog setup is described in the PK Specification. - ## The kernel clears TSR[WIS] prior to calling the handler. - - li %r4, PPE42_IRQ_WATCHDOG - - _update_kernel_context %r4, %r3 - - _liwa %r6, TSR_WIS - mttsr %r6 - - _lwzsd %r6, __ppe42_watchdog_routine - mtlr %r6 - blrl - - b check_for_ext_interrupt - - - ## Check if we can disard the interrupted context. - ## This routine expects r3, r4, lr, and cr to already be pushed. - ## It also expects r3 to hold the address of the function to jump - ## to after the interrupted context has been pushed (if necessary). - - .align 5 -ctx_check_discard: - - ## Prepare to jump to the branch function that was passed in - mtlr %r3 - - ## Check if the DISCARD_CTX bit is set in the kernel context - mfsprg0 %r3 - bb0wi %r3, PPE42_DISCARD_CTX_BIT, ctx_continue_push - -ctx_discard: - ## DISCARD_CTX bit was set. Discard stack and branch to interrupt - ## handler code - addi %r1, %r1, PK_CTX_SIZE - blr - - ## DISCARD_CTX bit was not set. Continue saving full context. - ## (r3, r4, lr, and cr have already been saved for us) and - ## r3 contains the interrupted kernel context - - .global __ctx_switch -__ctx_switch: - stwu %r1, -PK_CTX_SIZE(%r1) - stvd %d3, PK_CTX_GPR3(%r1) - mfcr %r3 - mflr %r4 - stvd %d3, PK_CTX_CR(%r1) - _liw %r3 __pk_next_thread_resume - mtlr %r3 - ## emulate what interrupt would do - mtsrr0 %r4 - mfmsr %r3 - mtsrr1 %r3 - - ## ctx_continue_push expects r3 to be value of sprg0 - mfsprg0 %r3 - -ctx_continue_push: - - stvd %d5, PK_CTX_GPR5(%r1) - stvd %d7, PK_CTX_GPR7(%r1) - stvd %d9, PK_CTX_GPR9(%r1) - stvd %d28, PK_CTX_GPR28(%r1) - stvd %d30, PK_CTX_GPR30(%r1) - mfxer %r5 - mfctr %r6 - stvd %d5, PK_CTX_XER(%r1) - mfsrr0 %r7 - mfsrr1 %r8 - stvd %d7, PK_CTX_SRR0(%r1) - stw %r0, PK_CTX_GPR0(%r1) - stw %r3, PK_CTX_KERNEL_CTX(%r1) - - ## If the 'processing interrupt' bit is set then we were already - ## using the kernel stack and don't need to modify or save the current - ## stack pointer. - bb1wi %r3, PPE42_PROC_IRQ_BIT, ctx_push_completed - - ## load the pointer to the current thread control block - _lwzsd %r4, __pk_current_thread - - ## don't save the stack pointer in the thread control block - ## if the current thread was the idle thread (null pointer) - bwz %r4, switch_to_kernel_stack - - ## we interrupted a bonafide thread, so save off the stack - ## pointer - stw %r1, PK_THREAD_OFFSET_SAVED_STACK_POINTER(%r4) - -switch_to_kernel_stack: - _stwsd %r1, __pk_saved_sp - _lwzsd %r1, __pk_kernel_stack - -ctx_push_completed: - blr - -__get_ext_irq: - - ## Entry invariants: - ## 1. external interupts are disabled; - ## 2. previous context has ben saved off - ## 3. r3 contains the kernel context - ## 4. r1 points to the kernel stack - - ## This is HW Macro specific code that is responsible for finding the - ## IRQ # and storing it in r4 (phantom IRQ's are assigned a value of EXTERNAL_IRQS). - - hwmacro_get_ext_irq - - ## An active or phantom IRQ was found. - ## R3 has the context of the interrupted thread or bottom half - ## R4 has the IRQ number. - ## 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 data ptr - ## R4 = irq - -call_external_irq_handler: - - _update_kernel_context %r4, %r3 - slwi %r3, %r4, 3 //multiply the irq# by 8 - _liw %r6, __ppe42_irq_handlers - lwzx %r5, %r6, %r3 - addi %r3, %r3, 4 - lwzx %r3, %r6, %r3 - mtlr %r5 - blrl - - ## Once the interrupt handler returns, check if any interrupts are - ## waiting and handle them now. - -check_for_ext_interrupt: - - ## Set the CTX_DISCARD bit in the kernel context so that if there is - ## an interrupt it will not bother saving the full context. - mfsprg0 %r31 - oris %r31, %r31, PPE42_DISCARD_CTX - mtsprg0 %r31 - - ###### Enable/Disable External Interrupts ##### - wrteei 1 - wrteei 0 - - ## If we made it this far, there must not be any interrupts pending. - ## If bottom half processing was interrupted we need to restore it -check_interrupted_bh: - - ## If the thread ID is 33 then the bottom half handler was interrupted - ## and needs to be restored. - extrwi %r4, %r31, 6, 2 - cmpwi %r4, 33 - beq ctx_pop_with_sprg0 - -check_for_bh: - ## if the bottom half queue is pointing to itself then the queue is - ## empty and there are no bottom halves that need processing. - _lwzsd %r4, _pk_bh_queue - lwz %r5, 0(%r4) - cmplwbeq %r4, %r5, restore_interrupted_sp - -process_bottom_halves: - ## Clear the CTX_DISCARD bit so that interrupted bottom half context - ## will be saved in case an interrupt occurs after this point. Also - ## set the thread ID to 33 so that we know to restore the bottom half - ## context that was interrupted. - rlwinm %r3, %r31, 0, 9, 1 //clear thread id + discard bit - oris %r3, %r3, 0x2100 //set thread id to 33 - mtsprg0 %r3 //set bottom half context - - ## branch to a C function that processes bottom halves - wrteei 1 - bl _pk_process_bh - wrteei 0 - - ## restore the previous kernel context (with discard bit set) - mtsprg0 %r31 - -restore_interrupted_sp: - ## restore the interrupted thread stack pointer - _lwzsd %r1, __pk_saved_sp - - ## If we are not in thread mode (i.e., we took an interrupt in an - ## interupt-only configuration of PK or after pk_initialize() but - ## before pk_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. - -check_thread_mode: - bb0wi %r31, PPE42_THREAD_MODE_BIT, ctx_pop_with_sprg0 - - ## Check if external interrupt activated a delayed context switch. The - ## C-level code has taken care of the scheduling decisions - we simply - ## need to implement them here. -check_for_ctx_switch: - - _lwzsd %r3, __pk_delayed_switch - bwz %r3, check_for_idle_thread - - ## Clear the delayed switch flag and go to the context switch code to - ## finish the switch. - - li %r3, 0 - _stwsd %r3, __pk_delayed_switch - - b __pk_next_thread_resume - - ## check if we should switch to the wait enabled state (idle) -check_for_idle_thread: - _lwzsd %r3, __pk_current_thread - bwz %r3, __pk_idle_thread - -ctx_pop_with_sprg0: - ## we must ensure that interrupts are disabled while restoring context - ## - ## restore sprg0 from the saved context - lwz %r0, PK_CTX_KERNEL_CTX(%r1) - mtsprg0 %r0 - -#if PK_KERNEL_TRACE_ENABLE - srwi %r0, %r0, 16 - PK_KERN_TRACE_ASM16("RESUME_CONTEXT(0x%04x)", %r0) -#endif - -ctx_pop: - lwz %r0, PK_CTX_GPR0(%r1) - lvd %d7, PK_CTX_SRR0(%r1) - mtsrr1 %r8 - mtsrr0 %r7 - lvd %d5, PK_CTX_XER(%r1) - mtctr %r6 - mtxer %r5 - lvd %d30, PK_CTX_GPR30(%r1) - lvd %d28, PK_CTX_GPR28(%r1) - lvd %d9, PK_CTX_GPR9(%r1) - lvd %d7, PK_CTX_GPR7(%r1) - lvd %d5, PK_CTX_GPR5(%r1) - lvd %d3, PK_CTX_CR(%r1) - mtlr %r4 - mtcr0 %r3 - lvd %d3, PK_CTX_GPR3(%r1) - addi %r1, %r1, PK_CTX_SIZE - - rfi - -/// \endcond diff --git a/pk/ppe42/ppe42_gcc.c b/pk/ppe42/ppe42_gcc.c deleted file mode 100644 index 97c2979c..00000000 --- a/pk/ppe42/ppe42_gcc.c +++ /dev/null @@ -1,305 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42_gcc.h -/// \brief 32-bit PowerPC functions expected by GCC -/// -/// GCC expects certain built-in functions to be defined in the environment. -/// Since PK 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 PK -/// 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 "pk.h" -#include "ppe42_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. - -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 __ppe42_udiv64() assembles to ??? bytes. The full C -// routine __ppc_sdiv64 compiles to ??? bytes with the most-negative checks, -// but only ??? bytes as configured here. - -// 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. -// - -uint64_t -__udivdi3(uint64_t u, uint64_t v) -{ - uint64_t quotient, remainder; - - __ppe42_udiv64(u, v, "ient, &remainder); - return quotient; -} - - -uint64_t -__umoddi3(uint64_t u, uint64_t v) -{ - uint64_t quotient, remainder; - - __ppe42_udiv64(u, v, "ient, &remainder); - return remainder; -} - - -#if 0 -#define INT64_T_MIN ((int64_t)(0x8000000000000000ull)) -#endif - -void -__ppe42_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 - - __ppe42_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; - - __ppe42_sdiv64(u, v, "ient, &remainder); - return quotient; -} - - -int64_t -__moddi3(int64_t u, int64_t v) -{ - int64_t quotient, remainder; - - __ppe42_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/pk/ppe42/ppe42_gcc.h b/pk/ppe42/ppe42_gcc.h deleted file mode 100644 index 8c4179cf..00000000 --- a/pk/ppe42/ppe42_gcc.h +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef __PPE42_GCC_H__ -#define __PPE42_GCC_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42_gcc.h -/// \brief 32-bit 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 -__ppe42_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 -__ppe42_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 /* __PPE42_GCC_H__ */ diff --git a/pk/ppe42/ppe42_init.c b/pk/ppe42/ppe42_init.c deleted file mode 100644 index a832e620..00000000 --- a/pk/ppe42/ppe42_init.c +++ /dev/null @@ -1,77 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42_init.c -/// \brief PPE42 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 "pk.h" -#include "pk_trace.h" - -// Note that __ppe42_system_setup() is called from the PK bootloader early -// in the initialization, at a point before the aplication has enabled -// interrupts. - -// This function is expected to be defined by the macro specific code (GPE, CME, SBE) -void __hwmacro_setup(void); - - -void -__ppe42_system_setup() -{ - //Only do this if the application hasn't provided a static table definition -#ifndef STATIC_IRQ_TABLE - PkIrqId irq; - - // Initialize the interrupt vectors. - for (irq = 0; irq < EXTERNAL_IRQS; irq++) { - __ppe42_irq_handlers[irq].handler = __ppe42_default_irq_handler; - } - - //NOTE: EXTERNAL_IRQS is the phantom interrupt assigned irq - __ppe42_irq_handlers[irq].handler = __ppe42_phantom_irq_handler; - - // Initialize special interrupt handlers - - __ppe42_fit_routine = __ppe42_default_irq_handler; - __ppe42_fit_arg = 0; - - __ppe42_watchdog_routine = __ppe42_default_irq_handler; - __ppe42_watchdog_arg = 0; - -/* - __ppe42_debug_routine = __ppe42_default_irq_handler; - __ppe42_debug_arg = 0; -*/ -#endif /*STATIC_IRQ_TABLE*/ - - //Clear all status bits in the TSR - mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS); - -#ifdef APPCFG_USE_EXT_TIMEBASE - //Enable the DEC interrupt and configure it to use the external dec_timer signal - mtspr(SPRN_TCR, TCR_DIE | TCR_DS); -#else - //Enable the DEC interrupt and configure it to use the internal clock signal - mtspr(SPRN_TCR, TCR_DIE); -#endif /* APPCFG_USE_EXT_TIMEBASE */ - -#if PK_TIMER_SUPPORT -#if PK_TRACE_SUPPORT -extern PkTraceBuffer g_pk_trace_buf; - //set the ppe instance id - g_pk_trace_buf.instance_id = (uint16_t)(mfspr(SPRN_PIR) & PIR_PPE_INSTANCE_MASK); -#endif /* PK_TRACE_SUPPORT */ -#endif /* PK_TIMER_SUPPORT */ - - //call macro-specific setup - __hwmacro_setup(); -} - - diff --git a/pk/ppe42/ppe42_irq.h b/pk/ppe42/ppe42_irq.h deleted file mode 100644 index 89948d60..00000000 --- a/pk/ppe42/ppe42_irq.h +++ /dev/null @@ -1,218 +0,0 @@ -#ifndef __PPE42_IRQ_H__ -#define __PPE42_IRQ_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42_irq.h -/// \brief PPE42 interrupt handling for PK -/// -/// Interrupt handling protocols and interrupt controller programming are -/// inherently non-portable, however PK defines APIs that may be useful among -/// different machines. -/// - - -// Define pseudo-IRQ numbers for PPE42 built-in interrupts. These numbers -// will appear in bits 16:23 of SPRG0 (__PkKernelContext) when the handlers -// are active - -#define PPE42_EXC_MACHINE_CHECK 0x50 -#define PPE42_EXC_DATA_STORAGE 0x53 -#define PPE42_EXC_INSTRUCTION_STORAGE 0x54 -#define PPE42_EXC_ALIGNMENT 0x56 -#define PPE42_EXC_PROGRAM 0x57 -#define PPE42_IRQ_DEC 0x58 -#define PPE42_IRQ_FIT 0x59 -#define PPE42_IRQ_WATCHDOG 0x5A - - -// 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 PPE42_MACHINE_CHECK_HANDLER -#define PPE42_MACHINE_CHECK_HANDLER PK_PANIC(0x0200) -#endif - -#ifndef PPE42_DATA_STORAGE_HANDLER -#define PPE42_DATA_STORAGE_HANDLER PK_PANIC(0x0300) -#endif - -#ifndef PPE42_INSTRUCTION_STORAGE_HANDLER -#define PPE42_INSTRUCTION_STORAGE_HANDLER PK_PANIC(0x0400) -#endif - -#ifndef PPE42_ALIGNMENT_HANDLER -#define PPE42_ALIGNMENT_HANDLER PK_PANIC(0x0600) -#endif - - -//////////////////////////////////////////////////////////////////////////// -// PK API -//////////////////////////////////////////////////////////////////////////// - -#ifndef __ASSEMBLER__ - -/// An IRQ handler takes 2 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 . - -typedef void (*PkIrqHandler)(void* arg, PkIrqId irq); - -/// Declare a subroutine as an IRQ handler - -#define PK_IRQ_HANDLER(f) void f(void* arg, PkIrqId irq) - -int pk_irq_setup(PkIrqId irq, - int polarity, - int trigger); - -int pk_irq_handler_set(PkIrqId irq, - PkIrqHandler handler, - void* arg); - -void pk_irq_enable(PkIrqId irq); -void pk_irq_disable(PkIrqId irq); -void pk_irq_statusclear(PkIrqId irq); - -PK_IRQ_HANDLER(__ppe42_default_irq_handler); -PK_IRQ_HANDLER(__ppe42_phantom_irq_handler); - - -int -ppe42_fit_setup(int tcr_fp, PkIrqHandler handler, void* arg); - - -/// The address of the optional FIT interrupt handler - -UNLESS__PPE42_IRQ_CORE_C__(extern) -volatile -PkIrqHandler __ppe42_fit_routine; - - -/// The private data of the optional FIT interrupt handler - -UNLESS__PPE42_IRQ_CORE_C__(extern) -volatile -void* __ppe42_fit_arg; - - -int -ppe42_watchdog_setup(int tcr_wp, int tcr_wrc, - PkIrqHandler handler, void* arg); - - -/// The address of the optional Watchdog interrupt handler - -UNLESS__PPE42_IRQ_CORE_C__(extern) -volatile -PkIrqHandler __ppe42_watchdog_routine; - - -/// The private data of the optional Watchdog interrupt handler - -UNLESS__PPE42_IRQ_CORE_C__(extern) -volatile -void* __ppe42_watchdog_arg; - - -int -ppe42_debug_setup(PkIrqHandler handler, void* arg); - - -/// The address of the optional Debug interrupt handler - -UNLESS__PPE42_IRQ_CORE_C__(extern) -volatile -PkIrqHandler __ppe42_debug_routine; - - -/// The private data of the optional Watchdog interrupt handler - -UNLESS__PPE42_IRQ_CORE_C__(extern) -volatile -void* __ppe42_debug_arg; - -#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 HWMACRO_GPE -#include "gpe_irq.h" -#else -#ifdef HWMACRO_STD -#include "std_irq.h" -#endif -#endif - -/// \page ppe42_irq_macros_page PPE42 PK IRQ Assembler Macros -/// -/// - -#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 { - PkIrqHandler handler; - void *arg; -} Ppe42IrqHandler; - - -#ifdef STATIC_IRQ_TABLE - -#define IRQ_HANDLER(func, arg) \ - {func, arg}, - -#define IRQ_HANDLER_DEFAULT \ - {__ppe42_default_irq_handler, 0}, - -#define EXTERNAL_IRQ_TABLE_END \ - {__ppe42_phantom_irq_handler, 0}\ -}; - -#define EXTERNAL_IRQ_TABLE_START \ - Ppe42IrqHandler __ppe42_irq_handlers[EXTERNAL_IRQS + 1] = \ -{ - -#else - -#define EXTERNAL_IRQ_TABLE_START - -#define IRQ_HANDLER(func, arg) - -#define IRQ_HANDLER_DEFAULT - -#define EXTERNAL_IRQ_TABLE_END - -#endif /*STATIC_IRQ_TABLE*/ - -/// Interrupt handlers for real (implemented interrupts) plus one for the phantom interrupt handler -extern Ppe42IrqHandler __ppe42_irq_handlers[EXTERNAL_IRQS + 1]; - - -/// 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__PPE42_IRQ_CORE_C__(extern) -Ppe42IrqHandler __ppe42_phantom_irq; - -#endif /* __ASSEMBLER__ */ - -#endif /* __PPE42_IRQ_H__ */ diff --git a/pk/ppe42/ppe42_irq_core.c b/pk/ppe42/ppe42_irq_core.c deleted file mode 100644 index 791f935d..00000000 --- a/pk/ppe42/ppe42_irq_core.c +++ /dev/null @@ -1,47 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42_irq_core.c -/// \brief Core IRQ routines required of any PPE42 configuration of PK -/// -/// 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 -/// PK application. - -#define __PPE42_IRQ_CORE_C__ - -#include "pk.h" - -#ifndef STATIC_IRQ_TABLE -Ppe42IrqHandler __ppe42_irq_handlers[EXTERNAL_IRQS + 1]; -#endif - -/// This function is installed by default for interrupts not explicitly set up -/// by the application. These interrupts should never fire. - -void -__ppe42_default_irq_handler(void* arg, PkIrqId irq) -{ - PK_PANIC(PPE42_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 -/// 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 interrupt input -/// to the PPE42 core. - -void __ppe42_phantom_irq_handler(void* arg, PkIrqId irq) -{ - PK_PANIC(PPE42_PHANTOM_INTERRUPT); -} - - -#undef __PPE42_IRQ_CORE_C__ diff --git a/pk/ppe42/ppe42_msr.h b/pk/ppe42/ppe42_msr.h deleted file mode 100644 index ac086dd6..00000000 --- a/pk/ppe42/ppe42_msr.h +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef __PPE42_MSR_H__ -#define __PPE42_MSR_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42_msr.h -/// \brief Everything related to the PPE42 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_SEM 0x7f000000 /* SIB Error Mask */ -#define MSR_IS0 0x00800000 /* Instance-Specific Field 0 */ -#define MSR_SIBRC 0x00700000 /* Last SIB return code */ -#define MSR_LP 0x00080000 /* Low Priority */ -#define MSR_WE 0x00040000 /* Wait State Enable */ -#define MSR_IS1 0x00020000 /* Instance-Specific Field 1 */ -#define MSR_UIE 0x00010000 /* Unmaskable Interrupt Enable */ -#define MSR_EE 0x00008000 /* External Interrupt Enable */ -#define MSR_ME 0x00001000 /* Machine Check Exception Enable */ -#define MSR_IPE 0x00000100 /* Imprecise Mode Enable */ -#define MSR_SIBRCA 0x000000ff /* SIB Return Code Accumulator */ - -//#define MSR_CE_BIT 14 -#define MSR_EE_BIT 16 -//#define MSR_IR_BIT 26 -//#define MSR_DR_BIT 27 - - -#define MSR_SEM_START_BIT 1 -#define MSR_SEM_LEN 7 -#define MSR_SIBRC_START_BIT 9 -#define MSR_SIBRC_LEN 3 - - -#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" : : "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" : : "i" (i) : "memory") - - -/// Write MSR[EE] from the EE bit of another MSR - -#define wrtee(other_msr) \ - asm volatile ("wrtee %0" : : "r" (other_msr) : "memory") - -#endif /* __ASSEMBLER__ */ - -#endif /* __PPE42_MSR_H__ */ diff --git a/pk/ppe42/ppe42_scom.c b/pk/ppe42/ppe42_scom.c deleted file mode 100755 index 105b83a4..00000000 --- a/pk/ppe42/ppe42_scom.c +++ /dev/null @@ -1,79 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2015 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42_scom.c -/// \brief Lowest level PK SCOM definitions. -/// -/// Currently these SCOM functions are only optimized for functionality, not -/// speed. Speed optimization will be done when we have full compiler support -/// for the low-level stvd and lvd SCOM OPs. -/// -/// A FAPI-lite SCOM can call these PK SCOM functions. -/// -/// Comment: -/// - No need to poll for SCOM completion, nor return error code of SCOM fails. -/// A SCOM fail will cause the GPE to hang if configured to do so. But do we -/// necessarily have to do this? Wouldn't a gentle recovery from a SCOM fail -/// be preferred? - -#include "pk.h" -#include "ppe42_scom.h" -#include "ppe42_msr.h" - - -uint32_t putscom_abs(const uint32_t i_address, uint64_t i_data) -{ - - // Perform the Store Virtual Double instruction - PPE_STVD(i_address, i_data); - - // Get the MSR[SIBRC] as the return code - uint32_t rc = mfmsr(); - rc = ((rc & MSR_SIBRC) >> (32-(MSR_SIBRC_START_BIT + MSR_SIBRC_LEN))); - return (rc); - -} - -uint32_t _putscom( uint32_t i_chiplet_id, uint32_t i_address, uint64_t i_data) -{ - - // Perform the Store Virtual Double Index instruction - PPE_STVDX(i_chiplet_id, i_address, i_data); - - // Get the MSR[SIBRC] as the return code - uint32_t rc = mfmsr(); - rc = ((rc & MSR_SIBRC) >> (32-(MSR_SIBRC_START_BIT + MSR_SIBRC_LEN))); - return (rc); - -} - -uint32_t getscom_abs( const uint32_t i_address, uint64_t *o_data) -{ - uint64_t temp; - // Perform the Load Virtual Double instruction - PPE_LVD(i_address, temp); - PPE_STVD(o_data, temp); - - // Get the MSR[SIBRC] as the return code - uint32_t rc = mfmsr(); - rc = ((rc & MSR_SIBRC) >> (32-(MSR_SIBRC_START_BIT + MSR_SIBRC_LEN))); - return (rc); -} - - -uint32_t _getscom( const uint32_t i_chiplet_id, const uint32_t i_address, uint64_t *o_data) -{ - uint64_t temp; - // Perform the Load Virtual Double Index instruction - PPE_LVDX(i_chiplet_id, i_address, temp); - PPE_STVD(o_data, temp); - - // Get the MSR[SIBRC] as the return code - uint32_t rc = mfmsr(); - rc = ((rc & MSR_SIBRC) >> (32-(MSR_SIBRC_START_BIT + MSR_SIBRC_LEN))); - return (rc); - -} diff --git a/pk/ppe42/ppe42_scom.h b/pk/ppe42/ppe42_scom.h deleted file mode 100755 index 33d998b5..00000000 --- a/pk/ppe42/ppe42_scom.h +++ /dev/null @@ -1,158 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/ppe/pk/ppe42/ppe42_scom.h $ */ -/* */ -/* OpenPOWER OnChipController Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2015 */ -/* [+] International Business Machines Corp. */ -/* */ -/* */ -/* Licensed under the Apache License, Version 2.0 (the "License"); */ -/* you may not use this file except in compliance with the License. */ -/* You may obtain a copy of the License at */ -/* */ -/* http://www.apache.org/licenses/LICENSE-2.0 */ -/* */ -/* Unless required by applicable law or agreed to in writing, software */ -/* distributed under the License is distributed on an "AS IS" BASIS, */ -/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ -/* implied. See the License for the specific language governing */ -/* permissions and limitations under the License. */ -/* */ -/* IBM_PROLOG_END_TAG */ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2015 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42_scom.h -/// \brief Include file for PK SCOMs -/// - -#ifndef __PK_SCOM_H__ -#define __PK_SCOM_H__ - -/// SCOM operations return non-zero error codes that may or may not indicate -/// an actual error, depending on which SCOM is begin accessed. This error -/// code will appear in the MSR[SIBRC] field, bits[9:11] right after the -/// SCOM OP returns. The error code value increases with the severity of the -/// error. -#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 - -#ifdef __cplusplus -extern "C" { -#endif - - -/// PPE Load Virtual Double operation -#define PPE_LVD(_m_address, _m_data) \ -asm volatile \ - ( \ - "lvd %[data], 0(%[address]) \n" \ - : [data]"=r"(_m_data) \ - : [address]"b"(_m_address) \ - ); - - -// PPE Store Virtual Double operation -#define PPE_STVD(_m_address, _m_data) \ -asm volatile \ - ( \ - "stvd %[data], 0(%[address]) \n" \ - : [data]"=&r"(_m_data) \ - : "[data]"(_m_data), \ - [address]"b"(_m_address) \ - : "memory" \ - ); - -/// PPE Load Virtual Double Indexed operation -#define PPE_LVDX(_m_base, _m_offset, _m_data) \ -asm volatile \ - ( \ - "lvdx %[data], %[base], %[offset] \n" \ - : [data]"=r"(_m_data) \ - : [base]"b"(_m_base), \ - [offset]"r"(_m_offset) \ - ); - - -// PPE Store Virtual Double Indexed operation -#define PPE_STVDX(_m_base, _m_offset, _m_data) \ -asm volatile \ - ( \ - "stvdx %[data], %[base], %[offset] \n" \ - : [data]"=&r"(_m_data) \ - : "[data]"(_m_data), \ - [base]"b"(_m_base), \ - [offset]"r"(_m_offset) \ - : "memory" \ - ); - -#define PPE_MFMSR(_m_data) \ -asm volatile \ - ( \ - "mfmsr %[data] \n" \ - : [data]"=&r"(*_m_data) \ - : "[data]"(*_m_data) \ - ); - -/// @brief putscom with absolute address -/// @param [in] i_address Fully formed SCOM address -/// @param [in] i_data Pointer to uint64_t data to be written. A pointer is used -/// to optimize the underlying hardware execution -/// -/// @retval On PPE42 platform, unmasked errors will take machine check interrupts -uint32_t putscom_abs(const uint32_t i_address, uint64_t i_data); - -/// @brief getscom with absolute address -/// @param [in] i_address Fully formed SCOM address -/// @param [in] *o_data Pointer to uint64_t data read -/// -/// @retval On PPE42 platform, unmasked errors will take machine check interrupts - -uint32_t getscom_abs( const uint32_t i_address, uint64_t *o_data); - -/// @brief Implementation of PPE putscom functionality -/// @param [in] i_chiplet Chiplet ID (@todo Should only be right justified) -/// @param [in] i_address Base SCOM address -/// @param [in] i_data Pointer to uint64_t data to be written. A pointer is used -/// to optimize the underlying hardware execution -/// -/// @retval On PPE42 platform, unmasked errors will take machine check interrupts -uint32_t _putscom( const uint32_t i_chiplet, const uint32_t i_address, uint64_t i_data); - - -/// @brief Implementation of PPE getscom functionality -/// @param [in] i_chiplet Chiplet ID (@todo Should only be right justified) -/// @param [in] i_address Base SCOM address -/// @param [in] i_data Pointer to uint64_t data read -/// -/// @retval On PPE42 platform, unmasked errors will take machine check interrupts -uint32_t _getscom( uint32_t i_chiplet, uint32_t i_address, uint64_t *o_data); - -extern inline uint32_t putscom(const uint32_t i_chiplet, const uint32_t i_address, uint64_t i_data) -{ - return _putscom(i_chiplet, i_address, i_data); -} - - -extern inline uint32_t getscom(const uint32_t i_chiplet, const uint32_t i_address, uint64_t *o_data) -{ - return _getscom(i_chiplet, i_address, o_data); -} - -#ifdef __cplusplus -} // extern C -#endif - -#endif // __PK_SCOM_H__ diff --git a/pk/ppe42/ppe42_spr.h b/pk/ppe42/ppe42_spr.h deleted file mode 100644 index b9a189e0..00000000 --- a/pk/ppe42/ppe42_spr.h +++ /dev/null @@ -1,173 +0,0 @@ -#ifndef __PPE42_SPR_H__ -#define __PPE42_SPR_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe42_spr.h -/// \brief Everything related to PPE42-specific SPRs - -/// \defgroup ppe42_sprs PPE42 SPRs -/// -/// These are the documented SPRs of the PPE42. 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_XER 0x001 /// Fixed-point exception register - #define SPRN_LR 0x008 /// Link register - #define SPRN_CTR 0x009 /// Count register - #define SPRN_DEC 0x016 /// Decrementer - #define SPRN_SRR0 0x01a /// Save/restore register 0 - #define SPRN_SRR1 0x01b /// Save/restore register 1 - #define SPRN_EDR 0x03d /// Error Data Register - #define SPRN_ISR 0x03e /// Interrupt Status Register - #define SPRN_IVPR 0x03f /// Interrupt Vector Prefix Register - #define SPRN_SPRG0 0x110 /// SPR general register 0 - #define SPRN_PIR 0x11e /// Processor Identification Register - #define SPRN_PVR 0x11f /// Processor version register - #define SPRN_DBCR 0x134 /// Debug Control Register - #define SPRN_DACR 0x13c /// Debug Address Compare Register - #define SPRN_TSR 0x150 /// Timer Status Register - #define SPRN_TCR 0x154 /// Timer Control Register - -/* DBCR - Debug Control Register */ - -#define DBCR_RST 0x30000000 /* Reset: 01=Soft Reset, 10=Hard Reset, 11=Halt */ -#define DBCR_TRAP 0x01000000 /* Trap Instruction Enable */ -#define DBCR_IACE 0x00800000 /* Instruction Address Compare Enable */ -#define DBCR_DACE 0x000c0000 /* Data Address Compare Enable: 01=store, 10=load, 11=both */ - -/* TCR - Timer Control Register */ - -#define TCR_WP_MASK 0xc0000000 /* Watchdog timer select bits */ -#define TCR_WP_0 0x00000000 /* WDT uses timer 0 */ -#define TCR_WP_1 0x40000000 /* WDT uses timer 1 */ -#define TCR_WP_2 0x80000000 /* WDT uses timer 2 */ -#define TCR_WP_3 0xc0000000 /* WDT uses timer 3 */ -#define TCR_WRC_MASK 0x30000000 /* Watchdog Reset Control mask */ -#define TCR_WRC_NONE 0x00000000 /* WDT results in no action */ -#define TCR_WRC_SOFT 0x10000000 /* WDT results in Soft reset */ -#define TCR_WRC_HARD 0x20000000 /* WDT results in Hard reset */ -#define TCR_WRC_HALT 0x30000000 /* WDT results in Halt */ -#define TCR_WIE 0x08000000 /* Watchdog Interrupt Enable */ -#define TCR_DIE 0x04000000 /* Decrementer Interrupt Enable */ -#define TCR_FP_MASK 0x03000000 /* FIT Timer Select bits*/ -#define TCR_FP_0 0x00000000 /* FIT uses timer 0 */ -#define TCR_FP_1 0x01000000 /* FIT uses timer 1 */ -#define TCR_FP_2 0x02000000 /* FIT uses timer 2 */ -#define TCR_FP_3 0x03000000 /* FIT uses timer 3 */ -#define TCR_FIE 0x00800000 /* FIT Interrupt Enable */ -#define TCR_DS 0x00400000 /* Decrementer timer select: 0=every cycle, 1=use dec_timer input signal */ - -#ifndef __ASSEMBLER__ - -typedef union { - uint32_t value; - struct { - unsigned int wp : 2; - unsigned int wrc : 2; - unsigned int wie : 1; - unsigned int die : 1; - unsigned int fp : 2; - unsigned int fie : 1; - unsigned int ds : 1; - unsigned int reserved : 22; - } fields; -} Ppe42TCR; - -#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_SOFT 0x10000000 /* Soft reset was forced by the watchdog */ -#define TSR_WRS_HARD 0x20000000 /* Hard reset was forced by the watchdog */ -#define TSR_WRS_HALT 0x30000000 /* Halt was forced by the watchdog */ -#define TSR_DIS 0x08000000 /* Decrementer Interrupt Status */ -#define TSR_FIS 0x04000000 /* FIT Interrupt Status */ - -/* PIR - Processor Identification Register */ -#define PIR_PPE_TYPE_MASK 0x000000E0 -#define PIR_PPE_TYPE_GPE 0x00000020 -#define PIR_PPE_TYPE_CME 0x00000040 -#define PIR_PPE_INSTANCE_MASK 0x0000001F - -#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)) - -#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 dbcr, SPRN_DBCR - _sprinstrs tcr, SPRN_TCR - _sprinstrs tsr, SPRN_TSR - _sprinstrs sprg0, SPRN_SPRG0 - _sprinstrs ivpr, SPRN_IVPR - _sprinstrs dec, SPRN_DEC - - /// \endcond - -#endif /* __ASSEMBLER__ */ - -#endif /* __PPE42_SPR_H__ */ diff --git a/pk/ppe42/ppe42_thread_init.S b/pk/ppe42/ppe42_thread_init.S deleted file mode 100644 index 7185f7c7..00000000 --- a/pk/ppe42/ppe42_thread_init.S +++ /dev/null @@ -1,110 +0,0 @@ -/// \file ppe42_thread_init.S -/// \brief PPE42-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 "pk.h" - .list - -/// \fn void __pk_thread_context_initialize(PkThread *thread, PkThreadRoutine 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 -/// pk_complete(). -#ifdef DOXYGEN_ONLY -void -__pk_thread_context_initialize(PkThread *thread, - PkThreadRoutine thread_routine, - void *private); -#endif -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \cond - - .global_function __pk_thread_context_initialize - -__pk_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 volatile context on the thread stack. The CR is cleared, - ## the LR = pk_complete(), R3 has the private parameter. - - lwz %r6, PK_THREAD_OFFSET_SAVED_STACK_POINTER(%r3) - - stwu %r6, -PK_CTX_SIZE(%r6) - - li %r7, 0 - stw %r7, PK_CTX_CR(%r6) - - _liw %r7, pk_complete - stw %r7, PK_CTX_LR(%r6) - - stw %r5, PK_CTX_GPR3(%r6) - - _gpr_init PK_CTX_GPR, 4, 0x0404 - _gpr_init PK_CTX_GPR, 5, 0x0505 - _gpr_init PK_CTX_GPR, 6, 0x0606 - - ## XER and CTR are clear, SRR0 = thread_routine, SRR1 = default machine - ## context. - - li %r7, 0 - stw %r7, PK_CTX_XER(%r6) - stw %r7, PK_CTX_CTR(%r6) - - stw %r4, PK_CTX_SRR0(%r6) - - _lwzsd %r7, __pk_thread_machine_context_default - stw %r7, PK_CTX_SRR1(%r6) - - _gpr_init PK_CTX_GPR, 0, 0x0000 - _gpr_init PK_CTX_GPR, 7, 0x0707 - _gpr_init PK_CTX_GPR, 8, 0x0808 - _gpr_init PK_CTX_GPR, 9, 0x0909 - _gpr_init PK_CTX_GPR, 10, 0x1010 - - ## Initialize the non-volatile context on the thread stack. - - _gpr_init PK_CTX_GPR, 28, 0x2828 - _gpr_init PK_CTX_GPR, 29, 0x2929 - _gpr_init PK_CTX_GPR, 30, 0x3030 - _gpr_init PK_CTX_GPR, 31, 0x3131 - - ## Initialize the kernel context on the thread stack. - ## Note: Thread priority is set later each time the thread is - ## resumed. - - lis %r7, PPE42_THREAD_MODE - stw %r7, PK_CTX_KERNEL_CTX(%r6) - - ## Initialization is done - the stack pointer is stored back in the - ## thread. - - stw %r6, PK_THREAD_OFFSET_SAVED_STACK_POINTER(%r3) - blr - - .epilogue __pk_thread_context_initialize - -/// \endcond diff --git a/pk/ppe42/ppe42_timebase.S b/pk/ppe42/ppe42_timebase.S deleted file mode 100644 index 54d28fa1..00000000 --- a/pk/ppe42/ppe42_timebase.S +++ /dev/null @@ -1,116 +0,0 @@ -/// \file ppe42_timebase.S -/// \brief PPE42-specific 64 bit timebase emulation -/// - .nolist -#include "pk.h" - .list - -/// \fn PkTimebase pk_timebase_get(void) -/// \brief Returns a 64 bit timebase -/// -#ifdef DOXYGEN_ONLY -PkTimebase -pk_timebase_get(void); -#endif -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \cond - .global ppe42_64bit_timebase - .global ppe42_tb_data - .global_function pk_timebase_get - -#ifndef APPCFG_USE_EXT_TIMEBASE - - /// Note that it is ok to use this function in a fast interrupt - /// context - .align 5 - .global_function pk_timebase32_get -pk_timebase32_get: - - //load the decrementer start time and change tag - lvd %r4, ppe42_tb_data@sda21(0) - - //load the lower 32 bits of the 64bit timebase accumulator - lwz %r3, ppe42_64bit_timebase+4@sda21(0) - - //load the current decrementer value - mfdec %r0 - - //load the change tag again (should already be in the cache) - lwz %r6, ppe42_tb_data+4@sda21(0) - - //loop until the change tag is the same (typically should be same) - cmplwbne %r5, %r6, pk_timebase32_get - - //calculate how much time has passed since the decrementer was started and store in r6 - subf %r5, %r0, %r4 - - //add the 32bit difference to our 32bit timebase accumulator - add %r3, %r5, %r3 - - blr - - -/// Use the DEC for our timebase until we have a real timebase register (uses -/// 9 instructions). -/// Note: It is not ok to use this function in a fast interrupt context due to -/// its use of r7 - .align 5 -pk_timebase_get: - - //load the decrementer start time and change tag - lvd %r5, ppe42_tb_data@sda21(0) - - //load 64bit timebase accumulator - lvd %r3, ppe42_64bit_timebase@sda21(0) - - - //load the current decrementer value - mfdec %r0 - - //load the change tag again (should already be in the cache) - lwz %r7, ppe42_tb_data+4@sda21(0) - - //loop until the change tag is the same - cmplwbne %r6, %r7, pk_timebase_get - - //calculate how much time has passed since the decrementer was started and store in r6 - subf %r6, %r0, %r5 - - //add the 32bit difference to the 64bit timebase accumulator - addc %r4, %r6, %r4 - addze %r3, %r3 - - blr - -//enable this once we have a local timebase register in the model -#else - -// use the local timebase register to keep more accurate time with just 6 instructions -// in the common case and 7 otherwise. - .align 5 -pk_timebase_get: - - //load the 64bit timebase accumulator - lvd r3, ppe42_64bit_timebase@sda21(0) - - //read the local timebase register (2 instructions) - _pk_timebase32_get r5, r5 - - //increment the upper 32 bits if the lower 32 bits have flipped - cmplwbge r5, r4, update_lower_32 - - //increment the upper 32 bits - addi r3, r3, 1 - -update_lower_32: - //replace the lower 32bits with what we read from the local timebase register - mr r4, r5 - - blr -#endif /* APPCFG_USE_EXT_TIMEBASE */ -/// \endcond |