From 0fb389ffd510e41cbf71e64ea8c1a3e9cd5caf2b Mon Sep 17 00:00:00 2001 From: Sachin Gupta Date: Tue, 16 Aug 2016 00:52:06 -0500 Subject: Use mirrored PK Change-Id: I8b990bf48bde9434f981dad4100a81bfe7a3c766 RTC: 158865 Reviewed-on: http://ralgit01.raleigh.ibm.com/gerrit1/28293 Tested-by: Jenkins Server Reviewed-by: Gregory S. Still Reviewed-by: Douglas R. Gilbert Reviewed-by: Shakeeb A. Pasha B K Reviewed-by: AMIT J. TENDOLKAR --- include/ppe_compiler.mk | 59 -- include/proc_hcd_common.H | 20 - include/std/algorithm | 762 ------------------- include/std/iterator | 185 ----- include/std/new | 40 - include/std/type_traits | 86 --- include/std/util/impl/iterator.h | 149 ---- include/std/util/impl/qsort.H | 191 ----- include/std/util/traits/has_lessthan.H | 40 - include/std/util/traits/has_minus.H | 40 - include/std/util/traits/has_plusequals.H | 40 - include/std/util/traits/impl/has_comparison.H | 135 ---- include/std/util/traits/remove_const.H | 71 -- pk/.empty | 0 pk/README | 8 - pk/gpe/Makefile | 50 -- pk/gpe/gpe.h | 35 - pk/gpe/gpe_common.h | 65 -- pk/gpe/gpe_init.c | 122 --- pk/gpe/gpe_irq.h | 247 ------ pk/gpe/gpe_irq_init.c | 106 --- pk/gpe/gpe_scom_handler.S | 98 --- pk/gpe/gpe_timebase.h | 40 - pk/gpe/pk_port.h | 16 - pk/gpe/pkgpefiles.mk | 33 - pk/kernel/.empty | 0 pk/kernel/Makefile | 26 - pk/kernel/pk.h | 125 --- pk/kernel/pk_api.h | 1016 ------------------------- pk/kernel/pk_bh_core.c | 29 - pk/kernel/pk_core.c | 79 -- pk/kernel/pk_debug_ptrs.c | 53 -- pk/kernel/pk_debug_ptrs.h | 39 - pk/kernel/pk_init.c | 196 ----- pk/kernel/pk_kernel.h | 246 ------ pk/kernel/pk_macros.h | 110 --- pk/kernel/pk_semaphore_core.c | 318 -------- pk/kernel/pk_semaphore_init.c | 82 -- pk/kernel/pk_stack_init.c | 85 --- pk/kernel/pk_thread.h | 56 -- pk/kernel/pk_thread_core.c | 573 -------------- pk/kernel/pk_thread_init.c | 134 ---- pk/kernel/pk_thread_util.c | 291 ------- pk/kernel/pk_timer_core.c | 401 ---------- pk/kernel/pk_timer_init.c | 62 -- pk/kernel/pkkernelfiles.mk | 32 - pk/ppe/Makefile | 50 -- pk/ppe/pk_port.h | 17 - pk/ppe/pkppefiles.mk | 33 - pk/ppe/ppe.h | 22 - pk/ppe/ppe_common.h | 49 -- pk/ppe/ppe_init.c | 25 - pk/ppe/ppe_timebase.h | 28 - pk/ppe42/.empty | 0 pk/ppe42/Makefile | 26 - pk/ppe42/div64.S | 248 ------ pk/ppe42/pk_port_types.h | 41 - pk/ppe42/pkppe42files.mk | 46 -- pk/ppe42/ppe42.h | 825 -------------------- pk/ppe42/ppe42_asm.h | 608 --------------- pk/ppe42/ppe42_boot.S | 169 ---- pk/ppe42/ppe42_cache.h | 102 --- pk/ppe42/ppe42_context.h | 201 ----- pk/ppe42/ppe42_core.c | 126 --- pk/ppe42/ppe42_exceptions.S | 501 ------------ pk/ppe42/ppe42_gcc.c | 305 -------- pk/ppe42/ppe42_gcc.h | 72 -- pk/ppe42/ppe42_init.c | 77 -- pk/ppe42/ppe42_irq.h | 218 ------ pk/ppe42/ppe42_irq_core.c | 47 -- pk/ppe42/ppe42_msr.h | 88 --- pk/ppe42/ppe42_scom.c | 79 -- pk/ppe42/ppe42_scom.h | 158 ---- pk/ppe42/ppe42_spr.h | 173 ----- pk/ppe42/ppe42_thread_init.S | 110 --- pk/ppe42/ppe42_timebase.S | 116 --- pk/std/Makefile | 50 -- pk/std/pk_port.h | 17 - pk/std/pkstdfiles.mk | 33 - pk/std/std.h | 20 - pk/std/std_common.h | 54 -- pk/std/std_init.c | 50 -- pk/std/std_irq.h | 86 --- pk/std/std_irq_config.h | 143 ---- pk/std/std_irq_init.c | 105 --- pk/std/std_register_addresses.h | 49 -- pk/std/std_timebase.h | 42 - pk/trace/Makefile | 26 - pk/trace/pk_trace.h | 279 ------- pk/trace/pk_trace_big.c | 92 --- pk/trace/pk_trace_binary.c | 91 --- pk/trace/pk_trace_core.c | 119 --- pk/trace/pktracefiles.mk | 39 - sbe/image/Makefile | 4 +- sbe/image/img_defs.mk | 10 +- tools/image/Makefile | 8 +- tools/ppetracepp/Makefile | 2 +- 97 files changed, 14 insertions(+), 12456 deletions(-) delete mode 100755 include/ppe_compiler.mk delete mode 100644 include/proc_hcd_common.H delete mode 100644 include/std/algorithm delete mode 100644 include/std/iterator delete mode 100755 include/std/new delete mode 100644 include/std/type_traits delete mode 100644 include/std/util/impl/iterator.h delete mode 100644 include/std/util/impl/qsort.H delete mode 100644 include/std/util/traits/has_lessthan.H delete mode 100644 include/std/util/traits/has_minus.H delete mode 100644 include/std/util/traits/has_plusequals.H delete mode 100644 include/std/util/traits/impl/has_comparison.H delete mode 100644 include/std/util/traits/remove_const.H delete mode 100644 pk/.empty delete mode 100644 pk/README delete mode 100644 pk/gpe/Makefile delete mode 100644 pk/gpe/gpe.h delete mode 100644 pk/gpe/gpe_common.h delete mode 100644 pk/gpe/gpe_init.c delete mode 100644 pk/gpe/gpe_irq.h delete mode 100644 pk/gpe/gpe_irq_init.c delete mode 100644 pk/gpe/gpe_scom_handler.S delete mode 100644 pk/gpe/gpe_timebase.h delete mode 100644 pk/gpe/pk_port.h delete mode 100644 pk/gpe/pkgpefiles.mk delete mode 100644 pk/kernel/.empty delete mode 100644 pk/kernel/Makefile delete mode 100644 pk/kernel/pk.h delete mode 100644 pk/kernel/pk_api.h delete mode 100644 pk/kernel/pk_bh_core.c delete mode 100644 pk/kernel/pk_core.c delete mode 100644 pk/kernel/pk_debug_ptrs.c delete mode 100644 pk/kernel/pk_debug_ptrs.h delete mode 100644 pk/kernel/pk_init.c delete mode 100644 pk/kernel/pk_kernel.h delete mode 100644 pk/kernel/pk_macros.h delete mode 100644 pk/kernel/pk_semaphore_core.c delete mode 100644 pk/kernel/pk_semaphore_init.c delete mode 100644 pk/kernel/pk_stack_init.c delete mode 100644 pk/kernel/pk_thread.h delete mode 100644 pk/kernel/pk_thread_core.c delete mode 100644 pk/kernel/pk_thread_init.c delete mode 100644 pk/kernel/pk_thread_util.c delete mode 100644 pk/kernel/pk_timer_core.c delete mode 100644 pk/kernel/pk_timer_init.c delete mode 100644 pk/kernel/pkkernelfiles.mk delete mode 100644 pk/ppe/Makefile delete mode 100644 pk/ppe/pk_port.h delete mode 100644 pk/ppe/pkppefiles.mk delete mode 100644 pk/ppe/ppe.h delete mode 100644 pk/ppe/ppe_common.h delete mode 100644 pk/ppe/ppe_init.c delete mode 100644 pk/ppe/ppe_timebase.h delete mode 100644 pk/ppe42/.empty delete mode 100644 pk/ppe42/Makefile delete mode 100644 pk/ppe42/div64.S delete mode 100644 pk/ppe42/pk_port_types.h delete mode 100644 pk/ppe42/pkppe42files.mk delete mode 100644 pk/ppe42/ppe42.h delete mode 100644 pk/ppe42/ppe42_asm.h delete mode 100644 pk/ppe42/ppe42_boot.S delete mode 100644 pk/ppe42/ppe42_cache.h delete mode 100644 pk/ppe42/ppe42_context.h delete mode 100644 pk/ppe42/ppe42_core.c delete mode 100644 pk/ppe42/ppe42_exceptions.S delete mode 100644 pk/ppe42/ppe42_gcc.c delete mode 100644 pk/ppe42/ppe42_gcc.h delete mode 100644 pk/ppe42/ppe42_init.c delete mode 100644 pk/ppe42/ppe42_irq.h delete mode 100644 pk/ppe42/ppe42_irq_core.c delete mode 100644 pk/ppe42/ppe42_msr.h delete mode 100755 pk/ppe42/ppe42_scom.c delete mode 100755 pk/ppe42/ppe42_scom.h delete mode 100644 pk/ppe42/ppe42_spr.h delete mode 100644 pk/ppe42/ppe42_thread_init.S delete mode 100644 pk/ppe42/ppe42_timebase.S delete mode 100644 pk/std/Makefile delete mode 100644 pk/std/pk_port.h delete mode 100644 pk/std/pkstdfiles.mk delete mode 100644 pk/std/std.h delete mode 100644 pk/std/std_common.h delete mode 100644 pk/std/std_init.c delete mode 100644 pk/std/std_irq.h delete mode 100644 pk/std/std_irq_config.h delete mode 100644 pk/std/std_irq_init.c delete mode 100644 pk/std/std_register_addresses.h delete mode 100644 pk/std/std_timebase.h delete mode 100644 pk/trace/Makefile delete mode 100644 pk/trace/pk_trace.h delete mode 100644 pk/trace/pk_trace_big.c delete mode 100644 pk/trace/pk_trace_binary.c delete mode 100644 pk/trace/pk_trace_core.c delete mode 100644 pk/trace/pktracefiles.mk diff --git a/include/ppe_compiler.mk b/include/ppe_compiler.mk deleted file mode 100755 index 7db9a4ca..00000000 --- a/include/ppe_compiler.mk +++ /dev/null @@ -1,59 +0,0 @@ -# Make header to set up PPE Compiler -# -ifndef CC_VERSION -export CC_VERSION = 4.8.3 -endif - -ifndef CC_TARGET -export CC_TARGET = powerpc-buildroot-linux-gnu -endif - -# GCC libraries -ifndef LIB_GCC_DIR -export LIB_GCC_DIR = $(CC_ROOT)/usr/lib/gcc/$(CC_TARGET)/$(CC_VERSION) -endif -LIB_DIRS += -L$(LIB_GCC_DIR) - -# GCC libraries -ifndef LIB_GCC_BASE -export LIB_GCC_BASE = $(CC_ROOT)/usr/lib/gcc/$(CC_TARGET) -endif -LIB_DIRS += -L$(LIB_GCC_BASE) - -# GCC libraries -ifndef LIB_BASE -export LIB_BASE = $(CC_ROOT)/usr/lib -endif -LIB_DIRS += -L$(LIB_BASE) - -# Shared Object C and C++ libraries -ifndef LIB_TARGET -export LIB_TARGET = $(CC_ROOT)/usr/$(CC_TARGET)/lib -endif -#CLIBS += $(LIB_TARGET)/libstdc++.a -#LIB_DIRS += -L$(LIB_TARGET) - -# Static C and C++ libraries -ifndef LIB_CLIB_DIR -export LIB_CLIB_DIR = $(CC_ROOT)/usr/$(CC_TARGET)/sysroot/lib -endif -LIB_DIRS += -L$(LIB_CLIB_DIR) - -# Runtime Static C and C++ libraries -ifndef LIB_CULIB_DIR -export LIB_CULIB_DIR = $(CC_ROOT)/usr/$(CC_TARGET)/sysroot/usr/lib -endif -LIB_DIRS += -L$(LIB_CULIB_DIR) - -GCCLIBS += $(LIB_CULIB_DIR)/libstdc++.a -GCCLIBS += $(LIB_CULIB_DIR)/libm.a -GCCLIBS += $(LIB_CULIB_DIR)/libc.a - -ifdef ENABLE_UCLIB -GCCLIBS += $(LIB_CULIB_DIR)/uclibc_nonshared.a -GCCLIBS += $(LIB_CULIB_DIR)/crt1.o -GCCLIBS += $(LIB_CULIB_DIR)/crti.o -endif - -GCCLIBS += $(LIB_GCC_DIR)/libgcc.a -GCCLIBS += $(LIB_GCC_DIR)/libgcc_eh.a diff --git a/include/proc_hcd_common.H b/include/proc_hcd_common.H deleted file mode 100644 index 51cc1285..00000000 --- a/include/proc_hcd_common.H +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __PROC_HCD_COMMON_H -#define __PROC_HCD_COMMON_H - -/// \file proc_hcd_common.H -/// \brief Standard bit-manipulation macros (C and Assembler) for PORE code - -/// \defgroup be64_bits Bit manipulation for 64-bit Big-Endian values -/// -/// \note These macros only work in the assembler context because we build our -/// assemblers to do 64-bit arithmetic, which is required for PORE assembly. -/// -/// @{ - -/// Create a multi-bit mask of \a n bits starting at bit \a b -#define BITS(b, n) ((ULL(0xffffffffffffffff) << (64 - (n))) >> (b)) - -/// Create a single bit mask at bit \a b -#define BIT(b) BITS((b), 1) - -#endif // __PROC_HCD_COMMON_H diff --git a/include/std/algorithm b/include/std/algorithm deleted file mode 100644 index e47671fd..00000000 --- a/include/std/algorithm +++ /dev/null @@ -1,762 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/include/algorithm $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2011,2014 */ -/* [+] 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 */ -#ifndef ALGORITHM -#define ALGORITHM - -#include -#include -#include - -#ifdef __cplusplus -namespace std -{ - /** - * Copy a range of elements - * @param[in] first InputIterator to the initial position in the source sequence. - * @param[in] last InputIterator to last position + 1 in the source sequence. - * @param[in] result OutputIterator to initial position in the destination sequence. - * @return an iterator to the last element in the destination range - * @note If both ranges overlap in such a way that result points to an elmenent in the source - * range then fuction copy_backward should be used. - */ - template - inline OutputIterator - copy (InputIterator first, InputIterator last, OutputIterator result ) - { - while(first!=last) - { - *result = *first; - ++result; - ++first; - } - return result; - } - - /** - * Copy a range of elements backwards - * @param[in] first Bidirectional iterator to the initial source position - * @param[in] last Bidirectional iterator to the final source position + 1 - * @param[in] result Bidirectional iterator to end of the destination sequence + 1. - * @return an iterator to the first element in the destination sequence. - * @note If both ranges overlap in such a way that result points to an element in the source - * range, the function copy should be used instead. - */ - template - inline BidirectionalIterator2 - copy_backward ( BidirectionalIterator1 first, - BidirectionalIterator1 last, - BidirectionalIterator2 result ) - { - while(last!=first) - { - --result; - --last; - *result = *last; - } - return result; - } - - /** - * Exchange values of two objects - * @param[in] a reference to an object to be swaped with b - * @param[in] b reference to an object to be swaped with a - * @note this function may not be an efficient way to swap large objects. - */ - template - inline void - swap(T& a, T&b ) - { - T c(a); - a=b; - b=c; - } - - /** - * Fill a range with value - * @param[in] first ForwardIterator to the first position in the source range. - * @param[in] last ForwardIterator to the last position +1 in the source range. - * @param[in] value reference to the object used to fill the sequence. - */ - template < class ForwardIterator, class T > - inline void - fill (ForwardIterator first, ForwardIterator last, const T& value ) - { - while (first != last) - { - *first = value; - ++first; - } - } - - /** - * Fill a sequence with value - * @param[in] first OutputIterator to the first position in the sequence. - * @param[in] n number of elements in the sequence - * @param[in] value reference to the value used to fill the sequence. - */ - template < class OutputIterator, class Size, class T > - inline void - fill_n( OutputIterator first, Size n, const T& value ) - { - for(; n>0; --n) - { - *first = value; - ++first; - } - } - - /** - * Fill a sequence with a generated value - * @param[in] first OutputIterator to the first position in the sequence. - * @param[in] n number of elements in the sequence - * @param[in] gen functor to create values used to fill the sequence. - */ - template - OutputIterator generate_n(OutputIterator first, Size n, Generator gen) - { - for(; n>0; --n) - { - *first = gen(); - ++first; - } - - return first; - } - - /** - * Return the lesser of two arguments - * @param[in] a object reference - * @param[in] b object reference - * @return reference to te lesser object - */ - template - inline const T& - min(const T& a, const T& b) - { - if( b < a) return b; - return a; - } - - /** - * Return the greater of two arguments - * @param[in] a object reference - * @param[in] b object reference - * @return reference to te greater object - */ - template - inline const T& - max(const T& a, const T& b) - { - if(a < b) return b; - return a; - } - - /** - * Find the location of an element within a range. - * @param[in] first InputIterator to the first position in the range. - * @param[in] last InputIterator to the last position in the range. - * @param[in] value Value to use for comparison. - * - * Returns the first iterator i in the range [first,last) such that - * (*i == value) or else last if no element is found. - * - * @return An iterator in the range [first,last]. last implies that no - * matching element was found. - */ - template - inline InputIterator - find(InputIterator first, InputIterator last, - const EqualityComparable& value) - { - while(first != last) - { - if ((*first) == value) - return first; - - ++first; - } - - return last; - } - - /** - * Find the location of an element within a range. - * @param[in] first InputIterator to the first position in the range. - * @param[in] last InputIterator to the last position in the range. - * @param[in] pred Predicate used to compare equality. - * - * Returns the first iterator i in the range [first,last) such that - * pred(*i) is true or else last if no element is found. - * - * @return An iterator in the range [first,last]. last implies that no - * matching element was found. - */ - template - inline InputIterator - find_if(InputIterator first, InputIterator last, - Predicate pred) - { - while(first != last) - { - if (pred(*first)) - return first; - - ++first; - } - - return last; - } - - /** - * Find the minimum element within a range. - * @param[in] first - FwdIterator to the first position in the range. - * @param[in] last - FwdIterator to the last position in the range. - * - * Returns the first element (i) such that (*j) < (*i) is false for all - * other iterators. - * - * The iterator last is returned only when the range contains no elements. - * - * @return An iterator in [first, last) containing the minimum element. - * - */ - template - inline FwdIterator min_element(FwdIterator first, FwdIterator last) - { - if (first == last) return last; - FwdIterator e = first++; - while(first != last) - { - if ((*first) < (*e)) - { - e = first; - } - ++first; - } - return e; - } - - /** - * Find the minimum element within a range. - * @param[in] first - FwdIterator to the first position in the range. - * @param[in] last - FwdIterator to the last position in the range. - * @param[in] comp - BinaryPredicate used to perform comparison. - * - * Returns the first element (i) such that comp(*j,*i) is false for all - * other iterators. - * - * The iterator last is returned only when the range contains no elements. - * - * @return An iterator in [first, last) containing the minimum element. - * - */ - template - inline FwdIterator min_element(FwdIterator first, FwdIterator last, - BinaryPredicate comp) - { - if (first == last) return last; - FwdIterator e = first++; - while(first != last) - { - if (comp((*first),(*e))) - { - e = first; - } - ++first; - } - return e; - } - - /** - * Find the maximum element within a range. - * @param[in] first - FwdIterator to the first position in the range. - * @param[in] last - FwdIterator to the last position in the range. - * - * Returns the first element (i) such that (*i) < (*j) is false for all - * other iterators. - * - * The iterator last is returned only when the range contains no elements. - * - * @return An iterator in [first, last) containing the minimum element. - * - */ - template - inline FwdIterator max_element(FwdIterator first, FwdIterator last) - { - if (first == last) return last; - FwdIterator e = first++; - while(first != last) - { - if ((*e) < (*first)) - { - e = first; - } - ++first; - } - return e; - } - - /** - * Find the maximum element within a range. - * @param[in] first - FwdIterator to the first position in the range. - * @param[in] last - FwdIterator to the last position in the range. - * @param[in] comp - BinaryPredicate used to perform comparison. - * - * Returns the first element (i) such that comp(*i,*j) is false for all - * other iterators. - * - * The iterator last is returned only when the range contains no elements. - * - * @return An iterator in [first, last) containing the minimum element. - * - */ - template - inline FwdIterator max_element(FwdIterator first, FwdIterator last, - BinaryPredicate comp) - { - if (first == last) return last; - FwdIterator e = first++; - while(first != last) - { - if (comp((*e),(*first))) - { - e = first; - } - ++first; - } - return e; - } - - - /** - * Find the element value in an ordered range [first, last]. Specifically, - * it returns the first position where value could be inserted without - * violating the ordering. - * - * @param[in] first ForwardIterator to the first position in the range. - * @param[in] last ForwardIterator to the last position in the range. - * @param[in] value Value to use for comparison. - */ - - template - inline ForwardIterator - lower_bound ( ForwardIterator first, - ForwardIterator last, - const LessThanComparable& value ) - { - ForwardIterator it; - int num = 0x0; - int range = std::distance( first, - last ); - - while( range > 0 ) - { - it = first; - num = range / 2; - std::advance( it, num ); - - if( (*it) < value ) - { - first = ++it; - range = (range - (num+1)); - } - else - { - range = num; - } - } - - return first; - } - - /** - * Find the element value in an ordered range [first, last]. Specifically, - * it returns the first position where value could be inserted without - * violating the ordering. This is done using the comparison function - * parameter that is passed in. - * - * @param[in] first ForwardIterator to the first position in the range. - * @param[in] last ForwardIterator to the last position in the range. - * @param[in] value Value to use for comparison. - * @param[in] comp Function to do the comparison - */ - template - inline ForwardIterator - lower_bound ( ForwardIterator first, - ForwardIterator last, - const T& value, - StrictWeakOrdering comp ) - { - ForwardIterator it; - int num = 0x0; - int range = std::distance( first, - last ); - - while( range > 0 ) - { - it = first; - num = range / 2; - std::advance( it, num ); - - if( comp( (*it), value ) ) - { - first = ++it; - range = (range - (num+1)); - } - else - { - range = num; - } - } - - return first; - } - - /** - * Apply a functor to each element in a range. - * - * Applies functor 'f' to each element in [first, last). - * - * @param[in] first - The beginning of the range. - * @param[in] last - The end of the range. - * @param[in] f - The functor. - * - * @return The functor after being having been applied. - */ - template - UnaryFunction for_each(InputIterator first, InputIterator last, - UnaryFunction f) - { - while(first != last) - { - f(*first); - ++first; - } - return f; - } - - /** - * Remove a value from a range. - * - * Removes all instances matching 'value' in the range [first, last) - * and returns an iterator to the end of the new range [first, new_last) - * where nothing in the new range has 'value'. - * - * Remove does not decrease the size of the container. - * - * @param[in] first - The beginning of the range. - * @param[in] last - The end of the range. - * @param[in] value - The value to remove. - * - * @return An iterator 'new_last' from [first, new_last). - */ - template - ForwardIterator remove(ForwardIterator first, ForwardIterator last, - const T& value) - { - // Find first match. - first = find(first, last, value); - - if (first == last) // No match found, return un-changed 'last'. - { - return last; - } - - // Match was found. 'new_last' is now the first removed element. - ForwardIterator new_last = first; - ++first; - - // Iterate through all the others. - while(first != last) - { - // If 'first' is a desired value, we need to copy it and move - // 'new_last'. - if (!(*first == value)) - { - *new_last = *first; - ++new_last; - } - - ++first; - } - - return new_last; - - } - - /** - * Remove a value from a range using a predicate. - * - * Removes all instances pred(*i) is true in the range [first, last) - * and returns an iterator to the end of the new range [first, new_last) - * where nothing in the new range has pred(*i) true. - * - * Remove does not decrease the size of the container. - * - * @param[in] first - The beginning of the range. - * @param[in] last - The end of the range. - * @param[in] pred - The predicate to use for comparison. - * - * @return An iterator 'new_last' from [first, new_last). - */ - template - ForwardIterator remove_if(ForwardIterator first, ForwardIterator last, - Predicate pred) - { - // Find first match. - first = find_if(first, last, pred); - - if (first == last) // No match found, return un-changed 'last'. - { - return last; - } - - // Match was found. 'new_last' is now the first removed element. - ForwardIterator new_last = first; - ++first; - - // Iterate through all the others. - while(first != last) - { - // If 'first' is a desired value, we need to copy it and move - // 'new_last'. - if (!(pred(*first))) - { - *new_last = *first; - ++new_last; - } - - ++first; - } - - return new_last; - - } - - /** - * Removes consecutive duplicate entries from a range. - * - * Removes all instances where (*i == *(i-1)) in the range [first, last) - * and returns an iterator to the end of the new range [first, new_last) - * where nothing in the new range is a consecutive duplicate. - * - * Unique does not decrease the size of the container. - * - * @param[in] first - The beginning of the range. - * @param[in] last - The end of the range. - * - * @return An iterator 'new_last' from [first, new_last). - * - */ - template - ForwardIterator unique(ForwardIterator first, ForwardIterator last) - { - // Trivial case of 0 items, return. - if (first == last) return last; - - // The algorithm keeps 3 iterators 'prev', 'first', and 'last'. The - // 'prev' iterator is always the last instance to be kept. 'last' is - // the end of the original range. 'first' is kept to be the item - // being compared. - - // Point 'prev' at the first element of the range since first item is - // a keeper. - ForwardIterator prev = first; - ++first; - - while (first != last) - { - // If the two items are not the same, we found a new item to keep. - if (!(*prev == *first)) - { - // Increment the "keep slot". - ++prev; - - // If the "keep slot" is not the element being compared, we - // need to move the new item down to that keep slot. - if (prev != first) - { - *prev = *first; - } - } - - // Advance to the next element. - ++first; - } - - // 'prev' points to the last item to be kept. Increment it to make - // it point to the one past. - ++prev; - return prev; - } - - /** - * Removes consecutive duplicate entries from a range by predicate. - * - * Removes all instances where pred(*i,*(i-1)) is true in the - * range [first, last) and returns an iterator to the end of the new - * range [first, new_last) where nothing in the new range is a - * consecutive duplicate. - * - * Unique does not decrease the size of the container. - * - * @param[in] first - The beginning of the range. - * @param[in] last - The end of the range. - * @param[in] pred - The predicate. - * - * @return An iterator 'new_last' from [first, new_last). - * - */ - template - ForwardIterator unique(ForwardIterator first, ForwardIterator last, - BinaryPredicate pred) - { - // Trivial case of 0 items, return. - if (first == last) return last; - - // The algorithm keeps 3 iterators 'prev', 'first', and 'last'. The - // 'prev' iterator is always the last instance to be kept. 'last' is - // the end of the original range. 'first' is kept to be the item - // being compared. - - // Point 'prev' at the first element of the range since first item is - // a keeper. - ForwardIterator prev = first; - ++first; - - while (first != last) - { - // If the two items are not the same, we found a new item to keep. - if (!(pred(*prev,*first))) - { - // Increment the "keep slot". - ++prev; - - // If the "keep slot" is not the element being compared, we - // need to move the new item down to that keep slot. - if (prev != first) - { - *prev = *first; - } - } - - // Advance to the next element. - ++first; - } - - // 'prev' points to the last item to be kept. Increment it to make - // it point to the one past. - ++prev; - return prev; - } - - /** Sort a range. - * - * Sorts all the elements in [first, last) using such that *i < *(i+1) - * for all items in the range. - * - * @param[in] first - The beginning of the range. - * @param[in] last - The end of the range. - */ - template - void sort(RandomAccessIterator first, RandomAccessIterator last) - { - Util::__Util_QSort_Impl::sort(first, last); - } - - /** Sort a range using a predicate - * - * Sorts all the elements in [first, last) using such that - * pred(*i, *(i+1)) is true for all items in the range. - * - * @param[in] first - The beginning of the range. - * @param[in] last - The end of the range. - * @param[in] pred - The predicate to use for comparison. - */ - template - void sort(RandomAccessIterator first, RandomAccessIterator last, - StrictWeakOrdering pred) - { - Util::__Util_QSort_Impl::sort(first, last, pred); - } - - /** Transform one sequence into another. - * - * Executes an operator against all elements in [first, last) and writes - * the result to another sequence. - * - * @param first - Beginning of the input range. - * @param last - Ending of the input range. - * @param result - Beginning of the output range. - * @param op - The transformation operator. - */ - template - OutputIterator transform(InputIterator first, InputIterator last, - OutputIterator result, UnaryFunction op) - { - while (first != last) - { - *result = op(*first); - ++result; - ++first; - } - return result; - } - - /** Transform two sequences into another. - * - * Executes an operator against all elements in [first1, last1) along - * with the peer from [first2, ...) and writes the result to - * another sequence. - * - * @param first1 - Beginning of the first input range. - * @param last1 - Ending of the first input range. - * @param first2 - Beginning of the second input range. - * @param result - Beginning of the output range. - * @param op - The transformation operator. - */ - template - OutputIterator transform(InputIterator1 first1, InputIterator1 last1, - InputIterator2 first2, OutputIterator result, - BinaryFunction op) - { - while (first1 != last1) - { - *result = op(*first1, *first2); - ++result; - ++first1; ++first2; - } - return result; - } - - - -}; -#endif - -#endif -/* vim: set filetype=cpp : */ diff --git a/include/std/iterator b/include/std/iterator deleted file mode 100644 index 396e1b59..00000000 --- a/include/std/iterator +++ /dev/null @@ -1,185 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/include/iterator $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* COPYRIGHT International Business Machines Corp. 2012,2014 */ -/* */ -/* 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 */ -#ifndef __STL_ITERATOR -#define __STL_ITERATOR - -#include - -#ifdef __cplusplus - -#include - -namespace std -{ - -/** @struct iterator_traits - * Template class defining a mapping typenames to ones defined in an iterator. - */ -template -struct iterator_traits -{ - typedef typename Iterator::value_type value_type; - typedef typename Iterator::difference_type difference_type; - typedef typename Iterator::pointer pointer; - typedef typename Iterator::reference reference; -}; - -/** @struct iterator_traits - * Template specialization of iterator traits for treating pointer types - * as an iterator. - */ -template -struct iterator_traits -{ - typedef T value_type; - typedef ptrdiff_t difference_type; - typedef T* pointer; - typedef T& reference; -}; - -/** Advance an iterator. - * - * @param[in] i - The iterator to advance. - * @param[in] n - The distance to advance the iterator. - * - * This function is equivalent to calling (++i) n times. - * - * If the iterator supports random access then this function will be - * implemented in linear time with respect to n. - * - */ -template -void advance(InputIterator& i, Distance n) -{ - Util::__Util_Iterator_Impl::advance(i, n); -} - -/** Determine the distance between two iterators. - * - * @param[in] first - The first iterator. - * @param[in] last - The last iterator. - * - * @return The distance between the two iterators. - * - * The distance between two iterators is the number of times first would - * need to be incremented so that it is equal to last. - * - * If the iterator supports random access then this function will be - * implemented in linear time with respect to the distance between the - * two iterators. A negative distance can only be obtained with random - * access iterators. - */ -template -typename iterator_traits::difference_type - distance(InputIterator first, InputIterator last) -{ - return Util::__Util_Iterator_Impl::distance< - InputIterator, - typename iterator_traits::difference_type> - (first, last); -} - -/** A OutputIterator which operates by push_back onto a container. - * - * See public std::back_insert_iterator documentation. - */ -template -class back_insert_iterator -{ - public: - // Common iterator typedefs. - typedef typename BackInsertionSequence::value_type value_type; - typedef typename BackInsertionSequence::difference_type difference_type; - typedef typename BackInsertionSequence::pointer pointer; - typedef typename BackInsertionSequence::reference reference; - - /** Default constructor from a container reference. */ - back_insert_iterator(BackInsertionSequence& s) : sequence(s) {}; - /** Copy constructor. Reuses container reference. */ - back_insert_iterator(const back_insert_iterator& i) - : sequence(i.sequence) {}; - - /** Assignment (copy) operator. */ - back_insert_iterator& operator=(const back_insert_iterator& i) - { - sequence = i.sequence; - return *this; - } - - /** Dereference operator. - * - * This is used to make the standard pattern '*i = x' work on - * an iterator. Since we need to 'push_back' into the - * container we don't actually return anything except ourself, - * which allows the operator= to be called. - */ - back_insert_iterator& operator*() { return *this; } - - /** Assignment operator. - * - * This is the second part of the standard pattern '*i = x'. - * - * Adds the value to the container by calling push_back. - * - * @param[in] v - The value to insert to the container. - */ - back_insert_iterator& operator=(const value_type& v) - { - sequence.push_back(v); - return *this; - } - - /** Preincrement operator - no-op */ - back_insert_iterator& operator++() { return *this; }; - /** Postincrement operator - no-op */ - back_insert_iterator& operator++(int unused) { return *this; }; - - private: - /** The container to insert into. */ - BackInsertionSequence& sequence; -}; - -/** Create a back_insert_iterator from a container. - * - * Utility function to allow back_insert_iterators to be created without - * needing to specify the underlying container type. - * - * Example: Reverse copy elements from one vector into a new vector. - * copy(v.rbegin(), v.rend(), back_inserter(v2)); - * - * @param[in] s - Sequence to create an iterator for. - * - * @return The back_insert_iterator. - */ -template -back_insert_iterator - back_inserter(BackInsertionSequence& s) -{ - return back_insert_iterator(s); -} - -}; // namespace std. -#endif - -#endif -/* vim: set filetype=cpp : */ diff --git a/include/std/new b/include/std/new deleted file mode 100755 index 8fd81bec..00000000 --- a/include/std/new +++ /dev/null @@ -1,40 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/include/new $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* COPYRIGHT International Business Machines Corp. 2011,2014 */ -/* */ -/* 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 */ -#ifndef __NEW_H -#define __NEW_H - -#ifdef __cplusplus -inline -void *operator new(size_t, void* place) -{ - return place; -} - -inline -void *operator new[](size_t, void* place) -{ - return place; -} -#endif - -#endif diff --git a/include/std/type_traits b/include/std/type_traits deleted file mode 100644 index 39394d8d..00000000 --- a/include/std/type_traits +++ /dev/null @@ -1,86 +0,0 @@ -#if !defined(_TYPE_TRAITS) -#define _TYPE_TRAITS - -namespace std -{ - /// integral_constant - template - struct integral_constant - { - static const _Tp value = __v; - typedef _Tp value_type; - typedef integral_constant<_Tp, __v> type; - }; - - /// typedef for true_type - typedef integral_constant true_type; - - /// typedef for false_type - typedef integral_constant false_type; - - template - const _Tp integral_constant<_Tp, __v>::value; - - /// remove_const - template - struct remove_const - { typedef _Tp type; }; - - /// remove_volatile - template - struct remove_volatile - { typedef _Tp type; }; - - /// remove_cv - template - struct remove_cv - { - typedef typename - remove_const::type>::type type; - }; - - template struct _is_integral_type : public false_type { }; - template<> struct _is_integral_type: public integral_constant {}; - template<> struct _is_integral_type: public integral_constant {}; - template<> struct _is_integral_type: public integral_constant {}; - template<> struct _is_integral_type: public integral_constant {}; - template<> struct _is_integral_type: public integral_constant {}; - template<> struct _is_integral_type: public integral_constant {}; - template<> struct _is_integral_type: public integral_constant {}; - template<> struct _is_integral_type: public integral_constant {}; - template<> struct _is_integral_type: public integral_constant {}; - template<> struct _is_integral_type: public integral_constant {}; - template<> struct _is_integral_type: public integral_constant {}; - template<> struct _is_integral_type: public integral_constant {}; - - /// is_integral - template - struct is_integral - : public integral_constant::type>::value)> - { }; - /// is_same - template - struct is_same - : public false_type { }; - - template - struct is_same<_Tp, _Tp> - : public true_type { }; - - template - struct __is_pointer_helper - : public false_type { }; - - template - struct __is_pointer_helper<_Tp*> - : public true_type { }; - - /// is_pointer - template - struct is_pointer - : public integral_constant::type>::value)> - { }; -} -#endif diff --git a/include/std/util/impl/iterator.h b/include/std/util/impl/iterator.h deleted file mode 100644 index fdb03145..00000000 --- a/include/std/util/impl/iterator.h +++ /dev/null @@ -1,149 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/include/util/impl/iterator.h $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2012,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 */ - -#ifndef __UTIL_IMPL_ITERATOR_H -#define __UTIL_IMPL_ITERATOR_H - -/** @file iterator.h - * - * Contains the internal implementation details of the stl header. - */ - -#include -#include - -namespace Util -{ - namespace __Util_Iterator_Impl - { - - /** - * Template definition of an iterator advance functor. - */ - template struct AdvanceImpl; - - /** - * Template specialization of the advance functor for iterators - * which do not support random access. - */ - template - struct AdvanceImpl - { - static void advance(InputIterator& i, Distance n) - { - while(n--) - ++i; - } - }; - - /** - * Template specialization of the advance functor for iterators - * which do support random access. - */ - template - struct AdvanceImpl - { - static void advance(RandomIterator& i, Distance n) - { - i += n; - } - }; - - /** - * Template wrapper function for the iterator advance. - * - * Uses the existence of a += operator on the iterator to determine - * if the random-access or non-random-access version should be used. - */ - template - void advance(InputIterator& i, Distance n) - { - AdvanceImpl::value - >::advance(i,n); - } - - /** - * Template definition of an iterator distance functor. - */ - template struct DistanceImpl; - - /** - * Template specialization of the distance functor for iterators - * which do not support random access. - */ - template - struct DistanceImpl - { - static Distance distance(InputIterator& first, - InputIterator& last) - { - Distance i = 0; - while (first != last) - { - ++i; - ++first; - } - return i; - } - }; - - /** - * Template specialization of the distance functor for iterators - * which do support random access. - */ - template - struct DistanceImpl - { - static Distance distance(RandomIterator& first, - RandomIterator& last) - { - return last - first; - } - }; - - /** - * Template wrapper function for the iterator distance. - * - * Uses the existence of a - operator on the iterator to determine - * if the random-access or non-random-access version should be used. - */ - template - Distance distance(InputIterator& first, - InputIterator& last) - { - return DistanceImpl::value - >::distance(first,last); - } - - }; -}; - -#endif diff --git a/include/std/util/impl/qsort.H b/include/std/util/impl/qsort.H deleted file mode 100644 index 718e3f64..00000000 --- a/include/std/util/impl/qsort.H +++ /dev/null @@ -1,191 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/include/util/impl/qsort.H $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* Contributors Listed Below - COPYRIGHT 2012,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 */ - -#ifndef __UTIL_IMPL_QSORT_H -#define __UTIL_IMPL_QSORT_H - -/** @file qsort.H - * - * Contains the internal implementation details of std::sort implemented as - * quick-sort. - */ - -#include - -// Forward declaration due to 'swap' being defined in which is -// including this file itself. -namespace std -{ - template void swap(T& a, T& b); -}; - -namespace Util -{ - namespace __Util_QSort_Impl - { - template - void sort(RandomAccessIterator first, RandomAccessIterator last) - { - size_t length = std::distance(first, last); - - // A range of length 0 or 1 is already sort. - if ((length == 0) || (length == 1)) - { - return; - } - - // A range of length 2 has a trivial sort. - if (length == 2) - { - RandomAccessIterator next = first; - std::advance(next, 1); - - if (*next < *first) - { - std::swap(*first, *next); - } - return; - } - - // Choose pivot as middle and move pivot to end. - // This is done to eliminate the O(n^2) behavior when the - // range is already sorted. - RandomAccessIterator pivot = first; - std::advance(pivot,length - 1); - RandomAccessIterator middle = first; - std::advance(middle, length / 2); - std::swap(*pivot, *middle); - - // Perform partitioning... - - // Division points to the first element greater than the pivot or - // else the farthest point partitioned if no elements greater than - // the pivot have been found yet. - RandomAccessIterator division = first; - RandomAccessIterator pos = first; - while(pos != pivot) - { - // Element less than the pivot is found, so move it to the - // "less than" side of the division line. - if (*pos < *pivot) - { - if (pos != division) - { - std::swap(*pos, *division); - } - ++division; - } - - ++pos; - } - - // Move the pivot down to the division line, which is its sorted - // position in the range. - if (pivot != division) - { - std::swap(*pivot,*division); - } - - // Sort each partition - __Util_QSort_Impl::sort(first,division); - std::advance(division, 1); - __Util_QSort_Impl::sort(division, last); - }; - - - template - void sort(RandomAccessIterator first, RandomAccessIterator last, - StrictWeakOrdering pred) - { - size_t length = std::distance(first, last); - - // A range of length 0 or 1 is already sort. - if ((length == 0) || (length == 1)) - { - return; - } - - // A range of length 2 has a trivial sort. - if (length == 2) - { - RandomAccessIterator next = first; - std::advance(next, 1); - - if (pred(*next,*first)) - { - std::swap(*first, *next); - } - return; - } - - // Choose pivot as middle and move pivot to end. - // This is done to eliminate the O(n^2) behavior when the - // range is already sorted. - RandomAccessIterator pivot = first; - std::advance(pivot,length - 1); - RandomAccessIterator middle = first; - std::advance(middle, length / 2); - std::swap(*pivot, *middle); - - // Perform partitioning... - - // Division points to the first element greater than the pivot or - // else the farthest point partitioned if no elements greater than - // the pivot have been found yet. - RandomAccessIterator division = first; - RandomAccessIterator pos = first; - while(pos != pivot) - { - // Element less than the pivot is found, so move it to the - // "less than" side of the division line. - if (pred(*pos,*pivot)) - { - if (pos != division) - { - std::swap(*pos, *division); - } - ++division; - } - - ++pos; - } - - // Move the pivot down to the division line, which is its sorted - // position in the range. - if (pivot != division) - { - std::swap(*pivot,*division); - } - - // Sort each partition. - __Util_QSort_Impl::sort(first,division,pred); - std::advance(division, 1); - __Util_QSort_Impl::sort(division, last,pred); - }; - - }; -}; - -#endif diff --git a/include/std/util/traits/has_lessthan.H b/include/std/util/traits/has_lessthan.H deleted file mode 100644 index 7a411468..00000000 --- a/include/std/util/traits/has_lessthan.H +++ /dev/null @@ -1,40 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/include/util/traits/has_lessthan.H $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* COPYRIGHT International Business Machines Corp. 2012,2014 */ -/* */ -/* 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 */ - -#ifndef __UTIL_TRAITS_HAS_LESSTHAN -#define __UTIL_TRAITS_HAS_LESSTHAN - -/** @file has_lessthan.H - * Creates a template class has_lessthan who's value variable will tell - * if T has a valid < comparison operation. - */ - -#define UTIL_COMPARISON_OPERATOR < -#define UTIL_COMPARISON_OPERATOR_NAME lessthan - -#include - -#undef UTIL_COMPARISON_OPERATOR -#undef UTIL_COMPARISON_OPERATOR_NAME - -#endif diff --git a/include/std/util/traits/has_minus.H b/include/std/util/traits/has_minus.H deleted file mode 100644 index ce3c59b7..00000000 --- a/include/std/util/traits/has_minus.H +++ /dev/null @@ -1,40 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/include/util/traits/has_minus.H $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* COPYRIGHT International Business Machines Corp. 2012,2014 */ -/* */ -/* 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 */ - -#ifndef __UTIL_TRAITS_HAS_MINUS -#define __UTIL_TRAITS_HAS_MINUS - -/** @file has_minus.H - * Creates a template class has_minus who's value variable will tell - * if T has a valid - operation. - */ - -#define UTIL_COMPARISON_OPERATOR - -#define UTIL_COMPARISON_OPERATOR_NAME minus - -#include - -#undef UTIL_COMPARISON_OPERATOR -#undef UTIL_COMPARISON_OPERATOR_NAME - -#endif diff --git a/include/std/util/traits/has_plusequals.H b/include/std/util/traits/has_plusequals.H deleted file mode 100644 index 5d66b403..00000000 --- a/include/std/util/traits/has_plusequals.H +++ /dev/null @@ -1,40 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/include/util/traits/has_plusequals.H $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* COPYRIGHT International Business Machines Corp. 2012,2014 */ -/* */ -/* 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 */ - -#ifndef __UTIL_TRAITS_HAS_PLUSEQUALS -#define __UTIL_TRAITS_HAS_PLUSEQUALS - -/** @file has_plusequals.H - * Creates a template class has_plusequals who's value variable will tell - * if T has a valid += operation. - */ - -#define UTIL_COMPARISON_OPERATOR += -#define UTIL_COMPARISON_OPERATOR_NAME plusequals - -#include - -#undef UTIL_COMPARISON_OPERATOR -#undef UTIL_COMPARISON_OPERATOR_NAME - -#endif diff --git a/include/std/util/traits/impl/has_comparison.H b/include/std/util/traits/impl/has_comparison.H deleted file mode 100644 index 61eae94c..00000000 --- a/include/std/util/traits/impl/has_comparison.H +++ /dev/null @@ -1,135 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/include/util/traits/impl/has_comparison.H $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* COPYRIGHT International Business Machines Corp. 2012,2014 */ -/* */ -/* 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 */ - -/** @file has_comparison.H - * - * Defines the guts of a has_foo template where 'foo' is a binary - * comparison operator on a type T. This template can be used for - * template meta-programming purposes. - * - * The macros UTIL_COMPARISON_OPERATOR and UTIL_COMPARISON_OPERATOR_NAME - * can be defined to create a template. For instance (<, lessthan) will - * create a template has_lessthan that allows determination to be made on - * if T has a valid < operator. - * - * This file purposefully omits an include-guard to allow multiple templates - * to be defined for all the various comparison operators. - * - * Notice that a heavy dose of SFINAE techniques follow. - */ - -// Ensure UTIL_COMPARISON_OPERATOR has been defined. -#ifndef UTIL_COMPARISON_OPERATOR - #error Comparison operator is not defined. -#endif - -// Ensure UTIL_COMPARISON_OPERATOR_NAME has been defined. -#ifndef UTIL_COMPARISON_OPERATOR_NAME - #error Comparison operator name is not defined. -#endif - -// Macro magic to make well-formed variable names from existing #defines. -#define __UTIL_TRAIT_COMPARISON_MAKENAME(X,Y) X ## Y -#define _UTIL_TRAIT_COMPARISON_MAKENAME(X,Y) \ - __UTIL_TRAIT_COMPARISON_MAKENAME(X,Y) -#define UTIL_TRAIT_COMPARISON_MAKENAME(X) \ - _UTIL_TRAIT_COMPARISON_MAKENAME(X,\ - UTIL_COMPARISON_OPERATOR_NAME) - -namespace Util -{ - -// Creates a namespace of the form Util::__Util_Trait_Impl_OPERATOR_NAME to -// hide the template implementation in. -namespace UTIL_TRAIT_COMPARISON_MAKENAME(__Util_Trait_Impl_) -{ - // If "T op S" is valid, it is going to return a type R. If it is not - // valid, we still need it to compile cleanly. So what we do is - // create a type (convert_from_any_type) that causes implicit type - // conversion from any other type. We ensure that the operator against - // convert_from_any_type returns a special type (bad_type). - // - // If "T op S" is valid then the implicit type conversion to - // convert_from_any_type will not happen because the native "T op S" takes - // precidence. So "T op S" has type not equal to bad_type. If "T op S" - // is invalid then the implicit type conversion will cause "T op S" to have - // type bad_type. - - struct bad_type {}; - struct convert_from_any_type - { - template convert_from_any_type(C const&); - }; - bad_type operator UTIL_COMPARISON_OPERATOR (const convert_from_any_type&, - const convert_from_any_type&); - - - // Now, "T op S" is going to return either bad_type or something else. We - // define a function 'has_comparison' that returns a character array of - // different size based on the input parameter type. Then the "sizeof" - // can be used to tell if "T op S" returns bad_type or something else. - // - // The only additional oddity is the get_instance function. Since some - // classes cannot be directly constructed, this is a level of indirection - // to get a type of T and S to apply the operator against. - template - struct UTIL_TRAIT_COMPARISON_MAKENAME(has_) - { - typedef char yes[1]; - typedef char no[2]; - - static no& has_comparison(bad_type); - static yes& has_comparison(_R); - - template static C& get_instance(); - - static const bool value = - sizeof(has_comparison(get_instance<_T>() UTIL_COMPARISON_OPERATOR - get_instance<_S>())) == sizeof(yes); - }; - -}; - - -// Since the implementation was hidden in a __Util_Trait_Impl_OPERATOR_NAME -// namespace, we expose just the main comparison class (with the value variable) -// by defining a class in the Traits namespace that inherits from the one in -// the __Util_Trait_Impl_OPERATOR_NAME namespace. -namespace Traits -{ - template - struct UTIL_TRAIT_COMPARISON_MAKENAME(has_) : - public UTIL_TRAIT_COMPARISON_MAKENAME(Util::__Util_Trait_Impl_):: - UTIL_TRAIT_COMPARISON_MAKENAME(has_)<_T,_S,_R> - {}; -}; - -}; - -#undef __UTIL_TRAIT_COMPARISON_MAKENAME -#undef _UTIL_TRAIT_COMPARISON_MAKENAME -#undef UTIL_TRAIT_COMPARISON_MAKENAME - diff --git a/include/std/util/traits/remove_const.H b/include/std/util/traits/remove_const.H deleted file mode 100644 index 2a7aabb4..00000000 --- a/include/std/util/traits/remove_const.H +++ /dev/null @@ -1,71 +0,0 @@ -/* IBM_PROLOG_BEGIN_TAG */ -/* This is an automatically generated prolog. */ -/* */ -/* $Source: src/include/util/traits/remove_const.H $ */ -/* */ -/* OpenPOWER HostBoot Project */ -/* */ -/* COPYRIGHT International Business Machines Corp. 2012,2014 */ -/* */ -/* 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 */ - -#ifndef __UTIL_TRAITS_REMOVE_CONST -#define __UTIL_TRAITS_REMOVE_CONST - -/** @file remove_const.H - * Creates a template class remove_const who's type typedef will strip the - * "const" from another type. - * - * Example: - * remove_const::type == int - * remove_const::type == int - * remove_const::type == int* - * - */ - -namespace Util -{ - namespace Traits - { - template struct remove_const; - - template - struct remove_const - { - typedef T type; - }; - - template - struct remove_const - { - typedef T* type; - }; - - template - struct remove_const - { - typedef T& type; - }; - - template - struct remove_const - { - typedef T type; - }; - - }; -}; - -#endif diff --git a/pk/.empty b/pk/.empty deleted file mode 100644 index e69de29b..00000000 diff --git a/pk/README b/pk/README deleted file mode 100644 index 2227ec37..00000000 --- a/pk/README +++ /dev/null @@ -1,8 +0,0 @@ -Subdirectories are organized as follows: - -kernel: Architecture-independent kernel code -ppe42: Kernel code that is common for all ppe42 instances -std: External interrupt support for standard ppe42 instances (SBE, CME, etc.) -gpe: External interrupt support for ppe42 instances residing in the OCC complex -ppe: Support for ppe42 instances that do not require or have external interrupts -trace: Kernel trace support diff --git a/pk/gpe/Makefile b/pk/gpe/Makefile deleted file mode 100644 index 324107dc..00000000 --- a/pk/gpe/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -# This Makefile compiles all of the PK code required for the GPE port -# of PK. See the "pk.mk" file in this directory. - -#all generated files from this makefile will end up in obj/$(IMAGE_NAME)/pk -export SUB_OBJDIR = /pk - -include img_defs.mk -include pkgpefiles.mk - -ifeq "$(PK_TIMER_SUPPORT)" "1" -GPE_OBJECTS += ${GPE-TIMER-C-SOURCES:.c=.o} ${GPE-TIMER-S-SOURCES:.S=.o} -endif - -ifeq "$(PK_THREAD_SUPPORT)" "1" -GPE_OBJECTS += ${GPE-THREAD-C-SOURCES:.c=.o} ${GPE-THREAD-S-SOURCES:.S=.o} -endif - -ifeq "$(GPE_ASYNC_SUPPORT)" "1" -GPE_OBJECTS += ${GPE-ASYNC-C-SOURCES:.c=.o} ${GPE-ASYNC-S-SOURCES:.S=.o} -endif - -OBJS := $(addprefix $(OBJDIR)/, $(GPE_OBJECTS)) - -libpk.a: kernel ppe42 trace gpe - $(AR) crs $(OBJDIR)/libpk.a $(OBJDIR)/*.o - -.PHONY: clean gpe kernel ppe42 trace -gpe: $(OBJS) - -trace: - $(MAKE) -I $(IMAGE_SRCDIR) -C ../trace - -kernel: - $(MAKE) -I $(IMAGE_SRCDIR) -C ../kernel - -ppe42: - $(MAKE) -I $(IMAGE_SRCDIR) -C ../ppe42 - - -$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) - -$(OBJDIR): - mkdir -p $(OBJDIR) - -clean: - rm -fr $(OBJDIR) - -ifneq ($(MAKECMDGOALS),clean) -include $(OBJS:.o=.d) -endif diff --git a/pk/gpe/gpe.h b/pk/gpe/gpe.h deleted file mode 100644 index 3b8e634e..00000000 --- a/pk/gpe/gpe.h +++ /dev/null @@ -1,35 +0,0 @@ -#ifndef __GPE_H__ -#define __GPE_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pgp.h -/// \brief The GPE environment for PK. - -// This is a 'circular' reference in PK, but included here to simplify PGAS -// programming. - -#ifndef HWMACRO_GPE -#define HWMACRO_GPE -#include "ppe42.h" -#endif - -#include "ocb_register_addresses.h" -#include "gpe_common.h" - -/* -#include "pcbs_register_addresses.h" -#include "pcbs_firmware_registers.h" - -#include "tod_register_addresses.h" -#include "tod_firmware_registers.h" - -#include "plb_arbiter_register_addresses.h" -#include "plb_arbiter_firmware_registers.h" - -*/ - -#endif /* __GPE_H__ */ diff --git a/pk/gpe/gpe_common.h b/pk/gpe/gpe_common.h deleted file mode 100644 index 043a4802..00000000 --- a/pk/gpe/gpe_common.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef __GPE_COMMON_H__ -#define __GPE_COMMON_H__ - -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file gpe_common.h -/// \brief Common header for GPE -/// -/// This header is maintained as part of the PK port for GPE, but needs to be -/// physically present in the PMX area to allow dropping PMX code as a whole -/// to other teams. - -// -*- WARNING: This file is maintained as part of PK. Do not edit in -*- -// -*- the PMX area as your edits will be lost. -*- - -#ifndef __ASSEMBLER__ -#include -#endif - -#include "occhw_common.h" - -/// Each GPE instance has it's own interrupt status register these macros -/// are added for convenience in accessing the correct register -#define GPE_GISR0(instance_id) (OCB_G0ISR0 + (instance_id * 8)) -#define GPE_GISR1(instance_id) (OCB_G0ISR1 + (instance_id * 8)) - -#ifdef __ASSEMBLER__ -/// This macro contains GPE specific code for determining what IRQ caused the -/// external exception handler to be invoked by the PPE - -/// Check for interrupts pending in status register 0 while the IRQ is -/// computed. The IRQ is expected to be stored in r4. If no IRQ is -/// pending then load the phantom irq # (EXTERNAL_IRQS). -/// -/// r1, r2, r3, and r13 must not be modified. All other registers may be used. -/// - .macro hwmacro_get_ext_irq - - _lwzi %r5, %r5, GPE_GISR0(APPCFG_OCC_INSTANCE_ID) - cntlzw %r4, %r5 - cmpwible %r4, 31, call_external_irq_handler #branch if irq is lt or eq to 31 - - ## No IRQ pending in interrupt set 0. Try set 1. - ## Note: irq # will be 64 (EXTERNAL_IRQS) if no bits were set in either register - - _lwzi %r6, %r6, GPE_GISR1(APPCFG_OCC_INSTANCE_ID) - cntlzw %r4, %r6 - addi %r4, %r4, 32 - - .endm - - -/// Redirect the .hwmacro_irq_cfg_bitmaps macro to call our macro that is common for both -/// GPE's and the 405 inside the OCC complex. This is called from the ppe42_exceptions.S -/// file. - .macro .hwmacro_irq_cfg_bitmaps - .occhw_irq_cfg_bitmaps - .endm -#endif /* __ASSEMBLER__ */ - -#endif /* __GPE_COMMON_H__ */ diff --git a/pk/gpe/gpe_init.c b/pk/gpe/gpe_init.c deleted file mode 100644 index b32c875b..00000000 --- a/pk/gpe/gpe_init.c +++ /dev/null @@ -1,122 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file gpe_init.c -/// \brief PK initialization for GPE -/// -/// The entry points in this routine are used during initialization. This -/// code space can be deallocated and reassigned after application -/// initialization if required. - -#include "pk.h" -#include "ocb_register_addresses.h" - -/// GPE environment initial setup. -/// -/// This is setup common to all GPE HW Macro applications. This setup takes place -/// during boot, before main() is called. - -void -__hwmacro_setup(void) -{ - uint64_t oirrA; - uint64_t oirrB; - uint64_t oirrC; - uint64_t owned_actual; - uint64_t reverse_polarity; - - //verify that this code is running on the correct GPE instance (one time check) - if((mfspr(SPRN_PIR) & PIR_PPE_INSTANCE_MASK) != APPCFG_OCC_INSTANCE_ID) - { - //APPCFG_OCC_INSTANCE_ID does not match actual instance ID! - PK_PANIC(OCCHW_INSTANCE_MISMATCH); - } - -#if (APPCFG_OCC_INSTANCE_ID == OCCHW_IRQ_ROUTE_OWNER) - //If this instance is the owner of the interrupt routting registers - //then write the routing registers for all OCC interrupts. - //This instance must be the first instance to run within the OCC - //This will be done while all external interrupts are masked. - PKTRACE("Initializing External Interrupt Routing Registers"); - out32(OCB_OIMR0_OR, 0xffffffff); - out32(OCB_OIMR1_OR, 0xffffffff); - out32(OCB_OIRR0A, (uint32_t)(g_ext_irqs_routeA >> 32)); - out32(OCB_OIRR1A, (uint32_t)g_ext_irqs_routeA); - out32(OCB_OIRR0B, (uint32_t)(g_ext_irqs_routeB >> 32)); - out32(OCB_OIRR1B, (uint32_t)g_ext_irqs_routeB); - out32(OCB_OIRR0C, (uint32_t)(g_ext_irqs_routeC >> 32)); - out32(OCB_OIRR1C, (uint32_t)g_ext_irqs_routeC); -#endif - - //Determine from the routing registers which irqs are owned by this instance - //NOTE: If a bit is not set in the routeA register, it is not owned by a GPE - - oirrA = ((uint64_t)in32(OCB_OIRR0A)) << 32; - oirrA |= in32(OCB_OIRR1A); - oirrB = ((uint64_t)in32(OCB_OIRR0B)) << 32; - oirrB |= in32(OCB_OIRR1B); - oirrC = ((uint64_t)in32(OCB_OIRR0C)) << 32; - oirrC |= in32(OCB_OIRR1C); - - //All interrupts routed to a GPE will have a bit set in routeA - owned_actual = oirrA; - - //wittle it down by bits in the routeB register -#if APPCFG_OCC_INSTANCE_ID & 0x2 - owned_actual &= oirrB; -#else - owned_actual &= ~oirrB; -#endif - - //wittle it down further by bits in the routeC register -#if APPCFG_OCC_INSTANCE_ID & 0x1 - owned_actual &= oirrC; -#else - owned_actual &= ~oirrC; -#endif - - //Panic if we don't own the irqs we were expecting - //NOTE: we don't panic if we are given more IRQ's than expected - if((owned_actual & g_ext_irqs_owned) != g_ext_irqs_owned) - { - //IRQ's were not routed to us correctly. - PK_PANIC(OCC_IRQ_ROUTING_ERROR); - } - - //Mask all external interrupts owned by this instance - //(even the ones given to us that we weren't expecting) - out32(OCB_OIMR0_OR, (uint32_t)(owned_actual >> 32)); - out32(OCB_OIMR1_OR, (uint32_t)owned_actual); - - //Set the interrupt type for all interrupts owned by this instance - out32(OCB_OITR0_CLR, (uint32_t)(g_ext_irqs_owned >> 32)); - out32(OCB_OITR1_CLR, (uint32_t)g_ext_irqs_owned); - out32(OCB_OITR0_OR, (uint32_t)(g_ext_irqs_type >> 32)); - out32(OCB_OITR1_OR, (uint32_t)g_ext_irqs_type); - - //Set the interrupt polarity for all interrupts owned by this instance - out32(OCB_OIEPR0_CLR, (uint32_t)(g_ext_irqs_owned >> 32)); - out32(OCB_OIEPR1_CLR, (uint32_t)g_ext_irqs_owned); - out32(OCB_OIEPR0_OR, (uint32_t)(g_ext_irqs_polarity >> 32)); - out32(OCB_OIEPR1_OR, (uint32_t)g_ext_irqs_polarity); - - //clear the status of all external interrupts owned by this instance - out32(OCB_OISR0_CLR, ((uint32_t)(g_ext_irqs_owned >> 32))); - out32(OCB_OISR1_CLR, ((uint32_t)g_ext_irqs_owned)); - - //set the status for interrupts that have reverse polarity - reverse_polarity = ~g_ext_irqs_polarity & g_ext_irqs_owned; - out32(OCB_OISR0_OR, ((uint32_t)(reverse_polarity >> 32))); - out32(OCB_OISR1_OR, ((uint32_t)reverse_polarity)); - - //Unmask the interrupts owned by this instance that are to be enabled by default - out32(OCB_OIMR0_CLR, (uint32_t)(g_ext_irqs_enable >> 32)); - out32(OCB_OIMR1_CLR, (uint32_t)g_ext_irqs_enable); - - //Wait for the last out32 operation to complete - sync(); - -} diff --git a/pk/gpe/gpe_irq.h b/pk/gpe/gpe_irq.h deleted file mode 100644 index 3b018916..00000000 --- a/pk/gpe/gpe_irq.h +++ /dev/null @@ -1,247 +0,0 @@ -#ifndef __GPE_IRQ_H__ -#define __GPE_IRQ_H__ - -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file occhw_irq.h -/// \brief GPE-OCCHW Interrupt handling for PK -/// -/// The OCCHW interrupt controller supports a maximum of 64 interrupts, split -/// into 2 x 32-bit non-cascaded interrupt controllers with simple OR -/// combining of the interrupt signals. -/// -/// The OCB interrupt controller allows interrupt status to be set directly by -/// software, as well as providing a mode that causes an enabled pending -/// interrupt to trigger an Unconditional Debug Event. The OCB interrupt -/// controller contains a 'mask' register, unlike other 405 interrupt -/// controllers that have an 'enable' register. The OCCHW mask and status -/// registers also have atomic CLR/OR function so that it is never necessary -/// to enter a critical section to enable/disable/clear interrupts and -/// interrupt status. - -#include "occhw_common.h" -#include "ocb_register_addresses.h" -#include "ppe42.h" - -#ifndef __ASSEMBLER__ - -/// Enable an interrupt by clearing the mask bit. - -UNLESS__PPE42_IRQ_CORE_C__(extern) -inline void -pk_irq_enable(PkIrqId irq) -{ - out32(OCCHW_OIMR_CLR(irq), OCCHW_IRQ_MASK32(irq)); -} - - -/// Disable an interrupt by setting the mask bit. - -UNLESS__PPE42_IRQ_CORE_C__(extern) -inline void -pk_irq_disable(PkIrqId irq) -{ - out32(OCCHW_OIMR_OR(irq), OCCHW_IRQ_MASK32(irq)); -} - - -/// Clear interrupt status with an CLR mask. Only meaningful for -/// edge-triggered interrupts. - -UNLESS__PPE42_IRQ_CORE_C__(extern) -inline void -pk_irq_status_clear(PkIrqId irq) -{ - out32(OCCHW_OISR_CLR(irq), OCCHW_IRQ_MASK32(irq)); -} - - -/// Get IRQ status as a 0 or non-0 integer - -UNLESS__PPE42_IRQ_CORE_C__(extern) -inline int -pk_irq_status_get(PkIrqId irq) -{ - return (in32(OCCHW_OISR(irq)) & OCCHW_IRQ_MASK32(irq)) != 0; -} - - -/// Set or clear interrupt status explicitly. - -UNLESS__PPE42_IRQ_CORE_C__(extern) -inline void -pk_irq_status_set(PkIrqId irq, int value) -{ - if (value) { - out32(OCCHW_OISR_OR(irq), OCCHW_IRQ_MASK32(irq)); - } else { - out32(OCCHW_OISR_CLR(irq), OCCHW_IRQ_MASK32(irq)); - } -} - - -#endif /* __ASSEMBLER__ */ - -/// \page occhw_irq_macros OCCHW IRQ API Assembler Macros -/// -/// These macros encapsulate the PK API for the OCCHW interrupt -/// controller. These macros require 2 scratch registers in addition to the \c -/// irq parameter register passed into the handler from PK interrupt -/// dispatch. These macros also modify CR0. -/// -/// \arg \c rirq A register that holds the \c irq parameter passed to -/// the handler from PK interrupt dispatch. This register is not -/// modified. -/// \arg \c rmask A scratch register - At the end of macro execution this -/// register contains the 32-bit mask form of the irq. -/// -/// \arg \c raddr A scratch register - At the end of macro execution this -/// register holds the address of the interrupt -/// controller facility that implements the action. -/// -/// \arg \c imm An immediate (0/non-0) value for certain macros. -/// -/// Forms: -/// -/// \b _pk_irq_enable \a rirq, \a rmask, \a raddr - Enable an \c irq. \n -/// \b _pk_irq_disable \a rirq, \a rmask, \a raddr - Disable an \c irq. \n -/// \b _pk_irq_status_clear \a rirq, \a rmask, \a raddr - Clear \c irq -/// interrupt status. \n -/// \b _pk_irq_status_set \a rirq, \a rmask, \a raddr, \a imm - Set \c irq status -/// with an immediate (0/non-0) value. \n -/// -/// \todo Once the logic design is locked down, revisit whether these macros -/// (and C-code versions) can be implemented without branching. This could be -/// done in theory by converting bit 26 into the byte offset between addresses -/// in interupt controller 0 and interrupt controller 1 - assuming the -/// distances are all the same power-of-two. -/// -/// \cond - -// IRQ numbers are in the range 0..63. IRQs are converted to the 32-bit -// residue used to compute the mask. CR0 is set as a test of IRQ > 32 - the -// register \c raddr is used as scratch for these computations. Hopefully the -// local labels 888 and 999 are unique enough. - -// Register names must be compared as strings - e.g., %r0 is not -// a symbol, it is converted to "0" by the assembler. - -#ifdef __ASSEMBLER__ - - .macro .two_unique, ra, rb - .ifnc \ra, \rb - .exitm - .endif - .error "Both register arguments must be unique" - .endm - - - .macro .three_unique, ra, rb, rc - .ifnc \ra, \rb - .ifnc \rb, \rc - .ifnc \ra, \rc - .exitm - .endif - .endif - .endif - .error "All three register arguments must be unique" - .endm - - - .macro _occhw_irq_or_mask, rirq:req, rmask:req - .two_unique \rirq, \rmask - lis \rmask, 0x8000 - srw \rmask, \rmask, \rirq - .endm - - .macro _occhw_irq_clr_mask, rirq:req, rmask:req - .two_unique \rirq, \rmask - _occhw_irq_or_mask \rirq, \rmask - .endm - - - .macro _pk_irq_enable, rirq:req, rmask:req, raddr:req - .three_unique \rirq, \rmask, \raddr - - andi. \raddr, \rirq, 0x20 - clrlwi \raddr, \rirq, 27 - _occhw_irq_clr_mask \raddr, \rmask - bne- 888f - _stwi \rmask, \raddr, OCB_OIMR0_CLR - b 999f -888: - _stwi \rmask, \raddr, OCB_OIMR1_CLR -999: - eieio - .endm - - - .macro _pk_irq_disable, rirq:req, rmask:req, raddr:req - .three_unique \rirq, \rmask, \raddr - - andi. \raddr, \rirq, 0x20 - clrlwi \raddr, \rirq, 27 - _occhw_irq_or_mask \raddr, \rmask - bne- 888f - _stwi \rmask, \raddr, OCB_OIMR0_OR - b 999f -888: - _stwi \rmask, \raddr, OCB_OIMR1_OR -999: - eieio - .endm - - - .macro _pk_irq_status_clear, rirq:req, rmask:req, raddr:req - .three_unique \rirq, \rmask, \raddr - - andi. \raddr, \rirq, 0x20 - clrlwi \raddr, \rirq, 27 - _occhw_irq_clr_mask \raddr, \rmask - bne- 888f - _stwi \rmask, \raddr, OCB_OISR0_CLR - b 999f -888: - _stwi \rmask, \raddr, OCB_OISR1_CLR -999: - eieio - .endm - - - .macro _pk_irq_status_set, rirq:req, rmask:req, raddr:req, imm:req - .three_unique \rirq, \rmask, \raddr - - andi. \raddr, \rirq, 0x20 - clrlwi \raddr, \rirq, 27 - - .if \imm - _occhw_irq_or_mask \raddr, \rmask - bne- 888f - _stwi \rmask, \raddr, OCB_OISR0_OR - b 999f -888: - _stwi \rmask, \raddr, OCB_OISR1_OR - - .else - - _occhw_irq_clr_mask \raddr, \rmask - bne- 888f - _stwi \rmask, \raddr, OCB_OISR0_CLR - b 999f -888: - _stwi \rmask, \raddr, OCB_OISR1_CLR - .endif - -999: - eieio - .endm - -#endif /* __ASSEMBLER__ */ - -/// \endcond - -#endif /* __GPE_IRQ_H__ */ diff --git a/pk/gpe/gpe_irq_init.c b/pk/gpe/gpe_irq_init.c deleted file mode 100644 index 061d5d10..00000000 --- a/pk/gpe/gpe_irq_init.c +++ /dev/null @@ -1,106 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2015 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file gpe_irq_init.c -/// \brief OCCHW IRQ initialization code for PK -/// -/// The entry points in this file are initialization rotines that could be -/// eliminated/deallocated by the application to free up storage if they are -/// no longer needed after initialization. - -#include "pk.h" - -/// Define the polarity and trigger condition for an interrupt. -/// -/// It is up to the application to take care of any side effects that may -/// occur from programming or reprogramming the interrupt controller. For -/// example, changing edge/level sensitivity or active level may set or clear -/// interrupt status in the controller. -/// -/// Note that PK allows this API to be called from any context, and changes -/// to the interrupt controller are made from a critical section. -/// -/// Return values other then PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_ARGUMENT_IRQ_SETUP One or more arguments are invalid, -/// including an invalid \a irq, or invalid \a polarity or \a trigger parameters. - -int -pk_irq_setup(PkIrqId irq, - int polarity, - int trigger) -{ - PkMachineContext ctx; - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(!OCCHW_IRQ_VALID(irq) || - !OCCHW_IRQ_OWNED(irq) || - !((polarity == PK_IRQ_POLARITY_ACTIVE_HIGH) || - (polarity == PK_IRQ_POLARITY_ACTIVE_LOW)) || - !((trigger == PK_IRQ_TRIGGER_LEVEL_SENSITIVE) || - (trigger == PK_IRQ_TRIGGER_EDGE_SENSITIVE)), - PK_INVALID_ARGUMENT_IRQ_SETUP); - } - - pk_critical_section_enter(&ctx); - - if (polarity == PK_IRQ_POLARITY_ACTIVE_HIGH) { - out32(OCCHW_OIEPR_OR(irq), OCCHW_IRQ_MASK32(irq)); - } else { - out32(OCCHW_OIEPR_CLR(irq), OCCHW_IRQ_MASK32(irq)); - } - - if (trigger == PK_IRQ_TRIGGER_EDGE_SENSITIVE) { - out32(OCCHW_OITR_OR(irq), OCCHW_IRQ_MASK32(irq)); - } else { - out32(OCCHW_OITR_CLR(irq), OCCHW_IRQ_MASK32(irq)); - } - - pk_critical_section_exit(&ctx); - - return PK_OK; -} - - -/// (Re)define the IRQ handler and priority for an interrupt. -/// Return values other then PK_OK (0) are errors; see \ref pk_errors -/// -/// Note that PK allows this API to be called from any context, and changes -/// to the interrupt controller are made from a critical section. -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_ARGUMENT_IRQ_HANDLER One or more arguments are -/// invalid, including an invalid \a irq, a null (0) \a handler, -/// or invalid \a priority. - -int -pk_irq_handler_set(PkIrqId irq, - PkIrqHandler handler, - void *arg) -{ - PkMachineContext ctx; - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(!OCCHW_IRQ_VALID(irq) || - (handler == 0), - PK_INVALID_ARGUMENT_IRQ_HANDLER); - } - - pk_critical_section_enter(&ctx); - - __ppe42_irq_handlers[irq].handler = handler; - __ppe42_irq_handlers[irq].arg = arg; - - pk_critical_section_exit(&ctx); - - return PK_OK; -} - - - diff --git a/pk/gpe/gpe_scom_handler.S b/pk/gpe/gpe_scom_handler.S deleted file mode 100644 index 44daa52b..00000000 --- a/pk/gpe/gpe_scom_handler.S +++ /dev/null @@ -1,98 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2015 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file gpe_scom_handler.S -/// \brief Interrupt handler code for SCOM requests from the ppc405 -/// - - .nolist -#include "pk.h" -#include "occhw_shared_data.h" - .list - - ## This function handles requests from the ppc405 to perform a getscom - ## or putscom operation. - ## - ## The ppc405 must supply a request in the following format: - ## - ## bytes : Content - ## ------------------- - ## 0-3 : Status - ## 4-7 : cmd/address (bit 0 is r/!w bit) - ## 8-15 : data (supplied by ppc405 on writes) - ## - ## Register Usage: - ## - ## r3: SRAM base address - ## r4: SCOM address - ## r5: MSR manipulation - ## d5: SCOM data - ## - ## NOTE: getscom requires 2 IC lines and 1 DC line - ## putscom requires 3 IC lines and 1 DC line - ## Both require the same number of instructions (16) - .align 5 - .global gpe_scom_handler -gpe_scom_handler: - - ## Load the hardcoded base address of the scom request - _liwa %r3, OSD_GPE_SCOM_ADDR - - ## Load the scom address from SRAM - lwz %r4, OCCHW_SCOM_ADDR_OFFSET(%r3) - - ## Mask all SIB errors - mfmsr %r7 - _oriwa %r5, %r7, MSR_SEM - mtmsr %r5 - - ## Check bit 0 of the scom address to determine if this - ## is a getscom or a putscom request - bb0wi %r4, 0, _do_putscom #branch if bit 0 is 0 - -_do_getscom: - ## the cmd bit was set, which means we're doing a getscom. - ## need to clear the bit first. - clrbwi %r4, %r4, 0 - - ## do the getscom - lvd %d5, 0(%r4) - - ## store the data into the request in SRAM - stvd %d5, OCCHW_SCOM_DATA_OFFSET(%r3) - -_get_scom_status: - - ## status is in the MSR, copy it to the scom request in SRAM - mfmsr %r5 - stw %r5, OCCHW_SCOM_STATUS_OFFSET(%r3) - - ## clear the IPI_SCOM interrupt: - ## first, load the bit we want to clear into a register - _liwa %r3, OCCHW_IRQ_MASK32(OCCHW_IRQ_IPI_SCOM) - - ## then, store it to the OISR0_CLR address - _stwi %r3, %r4, OCB_OISR0_CLR - - ## restore the MSR as it was before we changed it - mtmsr %r7 - - ## return - blr - -_do_putscom: - - ## load data from the request - lvd %d5, OCCHW_SCOM_DATA_OFFSET(%r3) - - ## do the putscom - stvd %d5, 0(%r4) - - b _get_scom_status - - - - diff --git a/pk/gpe/gpe_timebase.h b/pk/gpe/gpe_timebase.h deleted file mode 100644 index 648a3dcd..00000000 --- a/pk/gpe/gpe_timebase.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef __GPE_TIMEBASE_H__ -#define __GPE_TIMEBASE_H__ - -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2015 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file gpe_timebase.h -/// \brief support for using the OCB 32 bit timebase register -/// -/// The OCB timebase register is a 32 bit count-up register that is shared -/// by all GPE's in the OCC complex. - -#include "pk.h" - -#ifndef __ASSEMBLER__ - -#ifdef APPCFG_USE_EXT_TIMEBASE -static inline -uint32_t pk_timebase32_get(void) -{ - return in32(OCB_OTBR); -} - -#else -//assembly function is defined in ppe42_timebase.S -uint32_t pk_timebase32_get(void); - -#endif /* APPCFG_USE_EXT_TIMEBASE */ - -#else - - .macro _pk_timebase32_get rT, rA - _lwzi \rT, \rA, OCB_OTBR - .endm -#endif /* __ASSEMBLER__ */ - -#endif /* __GPE_TIMEBASE_H__ */ diff --git a/pk/gpe/pk_port.h b/pk/gpe/pk_port.h deleted file mode 100644 index 410f4356..00000000 --- a/pk/gpe/pk_port.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef __PK_PORT_H__ -#define __PK_PORT_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_port.h -/// \brief The top-level GPE environment header for PK. - -#define HWMACRO_GPE - -#include "ppe42.h" -#include "gpe_timebase.h" -#endif /* __PK_PORT_H__ */ diff --git a/pk/gpe/pkgpefiles.mk b/pk/gpe/pkgpefiles.mk deleted file mode 100644 index d7025b92..00000000 --- a/pk/gpe/pkgpefiles.mk +++ /dev/null @@ -1,33 +0,0 @@ -# @file pkgpefiles.mk -# -# @brief mk for including gpe object files -# -# @page ChangeLogs Change Logs -# @section pkgpefiles.mk -# @verbatim -# -# -# Change Log ****************************************************************** -# Flag Defect/Feature User Date Description -# ------ -------------- ---------- ------------ ----------- -# -# @endverbatim -# -########################################################################## -# Object Files -########################################################################## - -GPE-C-SOURCES = gpe_init.c gpe_irq_init.c -GPE-S-SOURCES = gpe_scom_handler.S - -GPE-TIMER-C-SOURCES = -GPE-TIMER-S-SOURCES = - -GPE-THREAD-C-SOURCES = -GPE-THREAD-S-SOURCES = - -GPE-ASYNC-C-SOURCES = -GPE-ASYNC-S-SOURCES = - -GPE_OBJECTS += $(GPE-C-SOURCES:.c=.o) $(GPE-S-SOURCES:.S=.o) - diff --git a/pk/kernel/.empty b/pk/kernel/.empty deleted file mode 100644 index e69de29b..00000000 diff --git a/pk/kernel/Makefile b/pk/kernel/Makefile deleted file mode 100644 index 3fad153e..00000000 --- a/pk/kernel/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 pkkernelfiles.mk - -ifeq "$(PK_TIMER_SUPPORT)" "1" -PK_OBJECTS += ${PK-TIMER-C-SOURCES:.c=.o} -endif - -ifeq "$(PK_THREAD_SUPPORT)" "1" -PK_OBJECTS += ${PK-THREAD-C-SOURCES:.c=.o} -endif - -OBJS := $(addprefix $(OBJDIR)/, $(PK_OBJECTS)) - -all: $(OBJS) - -$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) - -$(OBJDIR): - mkdir -p $(OBJDIR) - -ifneq ($(MAKECMDGOALS),clean) -include $(OBJS:.o=.d) -endif diff --git a/pk/kernel/pk.h b/pk/kernel/pk.h deleted file mode 100644 index 2efcdf11..00000000 --- a/pk/kernel/pk.h +++ /dev/null @@ -1,125 +0,0 @@ -#ifndef __PK_H__ -#define __PK_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk.h -/// \brief The combined header of the PK kernel. -/// -/// This header will be included in any C or assembler source file that -/// requires any of the PK API. All headers defined by PK and co-compiled -/// code should be protected such that they can be included without error into -/// assembly. - -#ifndef __ASSEMBLER__ -#include -#include -#endif /* __ASSEMBLER__ */ - -#ifndef __PK__ -#define __PK__ 1 -#endif - -/// The application environment specifies whether or not it will provide an -/// application configuration file, which must be named "pk_app_cfg.h". - -#ifndef USE_PK_APP_CFG_H -#define USE_PK_APP_CFG_H 0 -#endif - -#if USE_PK_APP_CFG_H -#include "pk_app_cfg.h" -#endif - -#include "pk_macros.h" -#include "pk_api.h" -#include "pk_port.h" -#include "pk_kernel.h" -//#include "pk_io.h" - -#ifndef __ASSEMBLER__ - -#define MIN(X, Y) \ - ({ \ - typeof (X) __x = (X); \ - typeof (Y) __y = (Y); \ - (__x < __y) ? __x : __y; }) - -#define MAX(X, Y) \ - ({ \ - typeof (X) __x = (X); \ - typeof (Y) __y = (Y); \ - (__x > __y) ? __x : __y; \ - }) - -/// \todo These don't require 32/64 bit versions, can always promote 32->64. - -#define FLOOR_LOG2_32(x) (32 - 1 - cntlz32(x)) -#define FLOOR_LOG2_64(x) (64 - 1 - cntlz64(x)) - -#define CEILING_LOG2(x) \ - ({ \ - uint64_t __x = (uint64_t)(x); \ - int __y; \ - __y = FLOOR_LOG2_64(__x); \ - if ((__x & (__x - 1)) != 0) { \ - __y++; \ - } \ - __y;}) - - -#define POW2_32(x) ((uint32_t)1 << (x)) -#define POW2_64(x) ((uint64_t)1 << (x)) - -/// Cast a pointer to another type -/// -/// This macro is necessary when casting a pointer to a longer integer type. -/// The pointer is first cast to the equivalent integer type 'unsigned long', -/// then cast to the final type. You can also use this to cast integers longer -/// than pointers back to pointers. - -#define CAST_POINTER(t, p) ((t)((unsigned long)(p))) - - -/// Create an alignment attribute. -#define ALIGNED_ATTRIBUTE(alignment) __attribute__ ((aligned (alignment))) - -/// Create a specific-section attribute -/// -/// Note that the section \a s here must be a string. Also note that data -/// specified to reside in specific sections must always be -/// initialized. Otherwise it confuses the linker which wants to put -/// uninitialized data into .bss sections. -/// -/// \code -/// -/// int foo SECTION_ATTRIBUTE(".noncacheable") = 0; -/// int bar[10] SECTION_ATTRIBUTE(".noncacheable") = {0}; -/// -/// \endcode -#define SECTION_ATTRIBUTE(s) __attribute__ ((section (s))) - -/// Create a 'used' attribute -/// -/// This is required for example to avoid "function unused" warnings when a -/// function is declared static but only referenced by inline assembler: -/// -/// \code -/// -/// static USED_ATTRIBUTE void -/// _checkstop(void* arg, PkIrqId irq, int priority) -/// { -/// PK_PANIC(VALIDATION_CHECKSTOP); -/// } -/// -/// PK_IRQ_FAST2FULL(_validationCheckstopHandler, _checkstop); -/// -/// \endcode -#define USED_ATTRIBUTE __attribute__ ((used)) - -#endif /* __ASSEMBLER__ */ - -#endif /* __PK_H__ */ diff --git a/pk/kernel/pk_api.h b/pk/kernel/pk_api.h deleted file mode 100644 index 66ed1324..00000000 --- a/pk/kernel/pk_api.h +++ /dev/null @@ -1,1016 +0,0 @@ -#ifndef __PK_API_H__ -#define __PK_API_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_api.h -/// \brief Macros and declarations for the PK API. - -// Basic constants - -/// Although the number of threads is defined as a manifest constant, -/// numerous parts of the PK code assume this definition. The number of -/// supported threads _can not_ be changed simply by changing this constant. - -#define PK_THREADS 32 - -#define PK_IDLE_THREAD_PRIORITY PK_THREADS - -// Interrupt API - -#define PK_IRQ_POLARITY_ACTIVE_LOW 0 -#define PK_IRQ_POLARITY_ACTIVE_HIGH 1 - -#define PK_IRQ_TRIGGER_LEVEL_SENSITIVE 0 -#define PK_IRQ_TRIGGER_EDGE_SENSITIVE 1 - -// API return codes - -#define PK_OK 0 -#define PK_ILLEGAL_CONTEXT_THREAD_CONTEXT 0x00779002 -#define PK_ILLEGAL_CONTEXT_INTERRUPT_CONTEXT 0x00779003 -#define PK_ILLEGAL_CONTEXT_THREAD 0x00779004 -#define PK_ILLEGAL_CONTEXT_TIMER 0x00779005 -#define PK_INVALID_THREAD_AT_RESUME1 0x00779007 -#define PK_INVALID_THREAD_AT_RESUME2 0x00779008 -#define PK_INVALID_THREAD_AT_SUSPEND1 0x00779009 -#define PK_INVALID_THREAD_AT_SUSPEND2 0x0077900a -#define PK_INVALID_THREAD_AT_DELETE 0x0077900b -#define PK_INVALID_THREAD_AT_INFO 0x0077900c -#define PK_INVALID_THREAD_AT_CHANGE 0x0077900d -#define PK_INVALID_THREAD_AT_SWAP1 0x0077900e -#define PK_INVALID_THREAD_AT_SWAP2 0x0077900f -#define PK_INVALID_THREAD_AT_CREATE 0x00779010 -#define PK_INVALID_SEMAPHORE_AT_POST 0x00779011 -#define PK_INVALID_SEMAPHORE_AT_PEND 0x00779012 -#define PK_INVALID_SEMAPHORE_AT_RELEASE 0x00779013 -#define PK_INVALID_SEMAPHORE_AT_INFO 0x00779014 -#define PK_INVALID_SEMAPHORE_AT_CREATE 0x00779015 -#define PK_INVALID_TIMER_AT_SCHEDULE 0x00779016 -#define PK_INVALID_TIMER_AT_CANCEL 0x00779017 -#define PK_INVALID_TIMER_AT_INFO 0x00779018 -#define PK_INVALID_TIMER_AT_CREATE 0x00779019 -#define PK_INVALID_ARGUMENT_IRQ_SETUP 0x0077901a -#define PK_INVALID_ARGUMENT_IRQ_HANDLER 0x0077901b -#define PK_INVALID_ARGUMENT_INTERRUPT 0x00779024 -#define PK_INVALID_ARGUMENT_CONTEXT_SET 0x00779025 -#define PK_INVALID_ARGUMENT_CONTEXT_GET 0x00779026 -#define PK_INVALID_ARGUMENT_FIT 0x00779027 -#define PK_INVALID_ARGUMENT_WATCHDOG 0x00779028 -#define PK_INVALID_ARGUMENT_INIT 0x00779029 -#define PK_INVALID_ARGUMENT_SEMAPHORE 0x0077902a -#define PK_INVALID_ARGUMENT_THREAD_CHANGE 0x0077902b -#define PK_INVALID_ARGUMENT_THREAD_PRIORITY 0x0077902c -#define PK_INVALID_ARGUMENT_THREAD1 0x0077902d -#define PK_INVALID_ARGUMENT_THREAD2 0x0077902e -#define PK_INVALID_ARGUMENT_THREAD3 0x0077902f -#define PK_STACK_OVERFLOW 0x00779030 -#define PK_TIMER_ACTIVE 0x00779031 -#define PK_TIMER_NOT_ACTIVE 0x00779032 -#define PK_PRIORITY_IN_USE_AT_RESUME 0x00779033 -#define PK_PRIORITY_IN_USE_AT_CHANGE 0x00779034 -#define PK_PRIORITY_IN_USE_AT_SWAP 0x00779035 -#define PK_SEMAPHORE_OVERFLOW 0x00779036 -#define PK_SEMAPHORE_PEND_NO_WAIT 0x00779037 -#define PK_SEMAPHORE_PEND_TIMED_OUT 0x00779038 -#define PK_SEMAPHORE_PEND_WOULD_BLOCK 0x00779039 -#define PK_INVALID_DEQUE_SENTINEL 0x0077903a -#define PK_INVALID_DEQUE_ELEMENT 0x0077903b -#define PK_INVALID_OBJECT 0x0077903c - -// Kernel panics - -#define PK_NO_TIMER_SUPPORT 0x0077903d -#define PK_START_THREADS_RETURNED 0x0077903e -#define PK_UNIMPLEMENTED 0x0077903f -#define PK_SCHEDULING_INVARIANT 0x00779040 -#define PK_TIMER_HANDLER_INVARIANT 0x00779041 -#define PK_THREAD_TIMEOUT_STATE 0x00779045 - -// Application-level panic offsets -// (Use these as offsets for your application code panics and keep -// track of them locally in your application code domain, including -// sharing the panic defines with other developers making codes -// for the same engine.) - -#define PK_APP_OFFSET_SBE 0x0077a000 -#define PK_APP_OFFSET_GPE0 0x0077b000 -#define PK_APP_OFFSET_GPE1 0x0077c000 -#define PK_APP_OFFSET_GPE2 0x0077d000 -#define PK_APP_OFFSET_GPE3 0x0077e000 -#define PK_APP_OFFSET_CME 0x0077f000 - -/// \defgroup pk_thread_states PK Thread States -/// -/// Threads are created in the state PK_THREAD_STATE_SUSPENDED_RUNNABLE. -/// When the thread is mapped it transitions to state PK_THREAD_STATE_MAPPED. -/// A mapped thread is runnable if it appears in the run queue; there is no -/// other flag or status to indicate a runnable thread. If a blocked thread -/// is suspended it goes into state PK_THREAD_STATE_SUSPENDED_BLOCKED. For -/// all threads the reason for blockage is detailed in the \a flags field of -/// the thread; See \ref pk_thread_flags. PK_THREAD_STATE_DELETED and -/// PK_THREAD_STATE_COMPLETED are effectively equivalent but named -/// individually for reporting purposes. -/// -/// \note This separation of the thread \a state and \a flags allows the use -/// of an PK semaphore as a thread barrier, as it supports a non-iterative -/// implementation of pk_semaphore_release_all() in which all threads blocked -/// on the semaphore are simultaneously inserted into the run queue with an -/// atomic operation, followed by each individual thread readjusting its flags -/// appropriately once the thread runs again. -/// -/// @{ - -#define PK_THREAD_STATE_SUSPENDED_RUNNABLE 1 -#define PK_THREAD_STATE_MAPPED 2 -#define PK_THREAD_STATE_SUSPENDED_BLOCKED 3 -#define PK_THREAD_STATE_COMPLETED 4 -#define PK_THREAD_STATE_DELETED 5 - -/// @} - - -/// \defgroup pk_thread_flags PK Thread Flags -/// -/// The \a flag field of the thread extends the information contained in the -/// \a state field; See \ref pk_thread_states. Blocked threads will show -/// PK_THREAD_FLAG_SEMAPHORE_PEND, PK_THREAD_FLAG_TIMER_PEND or both (if -/// blocked on a semaphore with timeout). The flag PK_THREAD_FLAG_TIMED_OUT -/// indicates that a thread timer timed out before the thread became -/// runnable. Currently only the semaphore-pend-with-timeout code uses this -/// flag. -/// -/// Note that a thread can be mapped and runnable (in the run queue) even -/// though PK_THREAD_FLAG_SEMAPHORE_PEND and/or PK_THREAD_FLAG_TIMER_PEND -/// are set. These flags are always cleared by the thread itself, not the code -/// that unblocks the thread. This allows the implementation of the -/// pk_semaphore_release_all() as explained in \ref pk_thread_states. -/// -/// @{ - -#define PK_THREAD_FLAG_SEMAPHORE_PEND 0x1 -#define PK_THREAD_FLAG_TIMER_PEND 0x2 -#define PK_THREAD_FLAG_TIMED_OUT 0x4 - -/// @} - - -// Critical Sections - -/// Enter a critical section, saving the current machine -/// context. - -#define pk_critical_section_enter(pctx) \ - pk_interrupt_disable(pctx) - -/// Exit a critical section by restoring the previous machine context. - -#define pk_critical_section_exit(pctx) \ - pk_machine_context_set(pctx) - - -/// Execute a statement atomically - -#define PK_ATOMIC(stmt) \ - do { \ - PkMachineContext __ctx; \ - pk_critical_section_enter(&__ctx); \ - stmt; \ - pk_critical_section_exit(&__ctx); \ - } while (0) - - -// Application-overrideable definitions - -/// Control whether or not the API functions check for errors. -/// -/// This definition can be overriden by the application. - -#ifndef PK_ERROR_CHECK_API -#define PK_ERROR_CHECK_API 1 -#endif - -/// Control whether API errors cause kernel panics or return negative error -/// codes. -/// -/// This selection is only valid if \c PK_ERROR_CHECK_API is defined -/// non-0. This definition can be overriden by the application. - -#ifndef PK_ERROR_PANIC -#define PK_ERROR_PANIC 1 -#endif - -/// Control whether or not the PK kernel checks key invariants. -/// -/// Violations of kernel invariants always cause kernel panics. This -/// definition can be overriden by the application. - -#ifndef PK_ERROR_CHECK_KERNEL -#define PK_ERROR_CHECK_KERNEL 1 -#endif - -/// Define the time interval type, which must be an unsigned type of a size -/// less then or equal to the size of \c PkTimebase. This definition can be -/// overridden by the application. - -#ifndef PK_TIME_INTERVAL_TYPE -#define PK_TIME_INTERVAL_TYPE uint32_t -#endif - -/// Provide support for the PkTimer APIs in addition to the default -/// initerrupt APIs. This definition can be overridden by the application. - -#ifndef PK_TIMER_SUPPORT -#define PK_TIMER_SUPPORT 1 -#endif - -/// Provide support for the all PK APIs. Thread support requires/implies -/// support for time services and semaphores. This definition can be -/// overridden by the application. - -#ifndef PK_THREAD_SUPPORT -#define PK_THREAD_SUPPORT 1 -#endif - -/// Control the level of stack checking. -/// -/// This definition can be overriden by the application. -/// -/// 0 : No stack prepatterning or checking is made for thread and kernel -/// stacks. -/// -/// 1 : Kernel interrupt stacks are prepatterned during -/// \c pk_initialize(). Thread stacks are prepatterned during -/// \c pk_thread_create(). -/// -/// 2 : (\b Default - Currently Unimplemented) In addition to prepatterning, -/// stack utilization is computed at the exit of context switches and -/// interrupt processing. The maximum utilization is stored in -/// the thread data structure. The kernel will panic if stack overflow is -/// detected. Stack utilization is not computed for the idle thread. - -#ifndef PK_STACK_CHECK -#define PK_STACK_CHECK 1 -#endif - -/// A hook for main() -/// -/// This hook macro is expanded in the body of __pk_main() prior to the call -/// of the application main(). The application can redefine this hook macro -/// in (or in headers referred to in) the application header -/// pk_app_cfg.h. The PK_MAIN_HOOK will run on the stack of main(). - -#ifndef PK_MAIN_HOOK -#define PK_MAIN_HOOK do {} while (0) -#endif - -/// A hook for pk_start_threads() -/// -/// This hook macro is expanded in the call-tree of pk_start_threads() before -/// threads are actually started. The application can redefine this hook -/// macro in (or in headers referred to in) the application header -/// pk_app_cfg.h. -/// -/// The PK_START_THREADS_HOOK runs as a pseudo-interrupt handler on the -/// kernel stack, with external interrupts disabled. - -#ifndef PK_START_THREADS_HOOK -#define PK_START_THREADS_HOOK do {} while (0) -#endif - -/// The maximum value of the \c PkTimebase type. - -#define PK_TIMEBASE_MAX ((PkTimebase)-1) - -/// A special value that specifies that the timebase will not be reset during -/// pk_init(). - -#define PK_TIMEBASE_CONTINUES PK_TIMEBASE_MAX - -/// By convention, a timeout value indicating 'no waiting' in a call of \c -/// pk_semaphore_pend(). - -#define PK_NO_WAIT 0 - -/// By convention, a timeout value indicating 'wait forever' in a call of \c -/// pk_semaphore_pend(). - -#define PK_WAIT_FOREVER ((PkInterval)-1) - -/// The PK timebase frequency in Hz -/// -/// Earlier version of PK defined the timbase frequency as a preprocessor -/// macro. Now, the timebase frequency is specified as a parameter of the -/// pk_initialize() API. The macro remains defined for backwards -/// compatibility, however all kernel uses of the timebase frequency are now -/// optimized around the timebase parameter. - -#define PK_TIMEBASE_FREQUENCY_HZ __pk_timebase_frequency_hz - -/// This is the unscaled timebase frequency in Hz. -#ifdef APPCFG_USE_EXT_TIMEBASE -#define PK_BASE_FREQ_HZ (uint32_t)25000000 -#else -#define PK_BASE_FREQ_HZ (uint32_t)400000000 -#endif /* APPCFG_USE_EXT_TIMEBASE */ -#define PK_BASE_FREQ_KHZ (PK_BASE_FREQ_HZ / 1000) -#define PK_BASE_FREQ_MHZ (PK_BASE_FREQ_HZ / 1000000) - -/// Scale a time interval to be _closer_ to what was actually requested -/// base on the actual timebase frequency. -#define PK_INTERVAL_SCALE(interval) ((interval) + ((interval) >> __pk_timebase_rshift)) - -/// Convert a time in integral seconds to a time interval - overflows are -/// ignored. The application can redefine this macro. - -#ifndef PK_SECONDS -#define PK_SECONDS(s) ((PkInterval)(PK_BASE_FREQ_HZ * (s))) -#endif - -/// Convert a time in integral milliseconds to a time interval - overflows are -/// ignored, and a frequency evenly (or closely) divisible by 1000 is -/// assumed. The application can redefine this macro. - -#ifndef PK_MILLISECONDS -#define PK_MILLISECONDS(m) ( (PkInterval)(PK_BASE_FREQ_KHZ * (m)) ) -#endif - -/// Convert a time in integral microseconds to a time interval - overflows are -/// ignored, and a frequncy evenly (or closely) divisible by 1,000,000 is -/// assumed. The application can redefine this macro. - -#ifndef PK_MICROSECONDS -#define PK_MICROSECONDS(u) ( (PkInterval)(PK_BASE_FREQ_MHZ * (u)) ) -#endif - -/// Convert a time in integral nanoseconds to a time interval - overflows are -/// ignored, and a frequeyncy evenly (or closely) divisible by 1,000,000 is -/// assumed. The application can redefine this macro. - -#ifndef PK_NANOSECONDS -#define PK_NANOSECONDS(n) ( (PkInterval)( ( ((PK_BASE_FREQ_MHZ<<10)/1000) * (n) ) >> 10) ) -#endif - - -/// Enable PK application tracing (enabled by default) -#ifndef PK_TRACE_ENABLE -#define PK_TRACE_ENABLE 1 -#endif - -/// Enable PK kernel tracing (disabled by default) -#ifndef PK_KERNEL_TRACE_ENABLE -#define PK_KERNEL_TRACE_ENABLE 0 -#endif - -//Application trace macros -#if !PK_TRACE_ENABLE -#define PK_TRACE(...) -#define PK_TRACE_BIN(str, bufp, buf_size) -#else -#define PK_TRACE(...) PKTRACE(__VA_ARGS__) -#define PK_TRACE_BIN(str, bufp, buf_size) PKTRACE_BIN(str, bufp, buf_size) -#endif - - -//Kernel trace macros -#if !PK_KERNEL_TRACE_ENABLE -#define PK_KERN_TRACE(...) -#define PK_KERN_TRACE_ASM16(...) -#else -#define PK_KERN_TRACE(...) PK_TRACE(__VA_ARGS__) -#define PK_KERN_TRACE_ASM16(...) PK_TRACE_ASM16(__VA_ARGS__) -#endif /* PK_KERNEL_TRACE_ENABLE */ - - -/// Add a string to the trace buffer with an optional register holding a 16bit value -/// WARNING: This calls a c function which may clobber any of the volatile registers -#if (PK_TRACE_SUPPORT && PK_TIMER_SUPPORT) -#define PK_TRACE_ASM16(...) TRACE_ASM_HELPER16(VARG_COUNT(__VA_ARGS__), __VA_ARGS__) -#else -#define PK_TRACE_ASM16(...) -#endif /* PK_TRACE_SUPPORT */ - -/// The following macros are helper macros for tracing. They should not be called -/// directly. -#define VARG_COUNT_HELPER(_0, _1, _2, _3, _4, _5, _6, _7, N, ...) N -#define VARG_COUNT(...) VARG_COUNT_HELPER(, ##__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0) - -#ifdef __ASSEMBLER__ -#define TRACE_ASM_HELPER16_CALL(count, ...) TINY_TRACE_ASM ## count (__VA_ARGS__) -#define TRACE_ASM_HELPER16(count, ...) TRACE_ASM_HELPER16_CALL(count, __VA_ARGS__) - -#define TINY_TRACE_ASM0() .error "format string required" -#define TINY_TRACE_ASM1(str) \ - .tiny_trace_asm1 trace_ppe_hash(str, PK_TRACE_HASH_PREFIX) -#define TINY_TRACE_ASM2(str, reg) \ - .tiny_trace_asm2 trace_ppe_hash(str, PK_TRACE_HASH_PREFIX), reg -#define TINY_TRACE_ASM3() .error "too many parameters" -#define TINY_TRACE_ASM4() .error "too many parameters" -#define TINY_TRACE_ASM5() .error "too many parameters" -#define TINY_TRACE_ASM6() .error "too many parameters" -#define TINY_TRACE_ASM7() .error "too many parameters" - -//TODO: add support for tracing more than 1 parameter and binary data in assembly - - .global pk_trace_tiny - - .macro .tiny_trace_asm1 hash16 - lis %r3, \hash16 - bl pk_trace_tiny - .endm - - .macro .tiny_trace_asm2 hash16, parm16 - clrlwi %r3, \parm16, 16 - oris %r3, %r3, \hash16 - bl pk_trace_tiny - .endm - -#endif /*__ASSEMBLER__*/ - - - -#ifndef __ASSEMBLER__ - -#include -#include - -/// The timebase frequency in Hz; A parameter to pk_initialize() -extern uint32_t __pk_timebase_frequency_hz; - -extern uint8_t __pk_timebase_rshift; - -/// The timebase frequency in KHz -extern uint32_t __pk_timebase_frequency_khz; - -/// The timebase frequency in Mhz -extern uint32_t __pk_timebase_frequency_mhz; - - -typedef unsigned long int PkAddress; - -typedef uint8_t PkThreadState; - -typedef uint8_t PkThreadPriority; - -typedef uint8_t PkThreadFlags; - -typedef uint32_t PkSemaphoreCount; - -typedef uint64_t PkTimebase; - -typedef PK_TIME_INTERVAL_TYPE PkInterval; - -#include "pk_port_types.h" - -typedef struct { - - /// A priority queue of threads pending on the semaphore. - PkThreadQueue pending_threads; - - /// The current semaphore count. - PkSemaphoreCount count; - - /// The maximum allowable count - for error checking. - PkSemaphoreCount max_count; - -} PkSemaphore; - - -/// Compile-time initialize a PkSemaphore structure -/// -/// This low-level macro creates a structure initializatin of an PkSemaphore -/// structure. This can be used for example to create compile-time initialized -/// arrays of semaphores. -#define PK_SEMAPHORE_INITIALIZATION(_initial_count, _max_count) \ - {.pending_threads = 0, \ - .count = (_initial_count), \ - .max_count = (_max_count)} - - -/// Declare and initialize a semaphore -#define PK_SEMAPHORE(sem, initial_count, max_count) \ - PkSemaphore sem = PK_SEMAPHORE_INITIALIZATION(initial_count, max_count) - - -/// Trace macros for C functions -#define HASH_ARG_COMBO(str, arg) \ - ((((uint32_t)trace_ppe_hash(str, PK_TRACE_HASH_PREFIX)) << 16) | ((uint32_t)(arg) & 0x0000ffff)) - -#define PKTRACE0(...) pk_trace_tiny() //will fail at compile time - -#define PKTRACE1(str) \ - pk_trace_tiny((trace_ppe_hash(str, PK_TRACE_HASH_PREFIX) << 16)) - -#define PKTRACE2(str, parm0) \ - ((sizeof(parm0) <= 2)? \ - pk_trace_tiny(HASH_ARG_COMBO(str, parm0)): \ - pk_trace_big(HASH_ARG_COMBO(str, 1), ((uint64_t)parm0) << 32, 0)) - -#define PKTRACE3(str, parm0, parm1) \ - pk_trace_big(HASH_ARG_COMBO(str, 2), ((((uint64_t)parm0) << 32) | parm1), 0) - -#define PKTRACE4(str, parm0, parm1, parm2) \ - pk_trace_big(HASH_ARG_COMBO(str, 3), ((((uint64_t)parm0) << 32) | parm1),\ - ((uint64_t)parm2) << 32 ) - -#define PKTRACE5(str, parm0, parm1, parm2, parm3) \ - pk_trace_big(HASH_ARG_COMBO(str, 4), ((((uint64_t)parm0) << 32) | parm1),\ - ((((uint64_t)parm2) << 32) | parm3) ) - -#define PKTRACE6(...) pk_trace_tiny() //will fail at compile time -#define PKTRACE7(...) pk_trace_tiny() //will fail at compile time - -#define PKTRACE_HELPER2(count, ...) PKTRACE ## count (__VA_ARGS__) -#define PKTRACE_HELPER(count, ...) PKTRACE_HELPER2(count, __VA_ARGS__) - -#if (PK_TRACE_SUPPORT && PK_TIMER_SUPPORT) -#define PKTRACE(...) PKTRACE_HELPER(VARG_COUNT(__VA_ARGS__), __VA_ARGS__) -#define PKTRACE_BIN(str, bufp, buf_size) \ - pk_trace_binary(((buf_size < 255)? HASH_ARG_COMBO(str, buf_size): HASH_ARG_COMBO(str, 255)), bufp) -#else -#define PKTRACE(...) -#define PKTRACE_BIN(str, bufp, buf_size) -#endif //PK_TRACE_SUPPORT - - - -/// A generic doubly-linked list object -/// -/// This object functions both as a sentinel mode for a deque as well as a -/// pointer container for elements in deques. The PK API assumes that -/// queueable structures will be defined with an PkDeque structure as the -/// initial 'data member' of the structure. This allows a pointer to a queue -/// element to be cast to a pointer to an PkDeque and vice-versa. - -typedef struct PkDeque { - - /// Pointer to the head or the next element in a deque. - /// - /// When an PkDeque is used as the sentinel node for a queue, \a next - /// points to the head of the queue, and the condition (next == \) - /// indicates an empty PkDeque. By convention the condition (\a next == - /// 0) is used to indicate that a queue element is not enqueued. - struct PkDeque* next; - - /// Pointer to the tail or previous element in a deque. - /// - /// When a DQueue is used as the sentinel node for a queue, \a previous - /// points to the tail of the queue. - struct PkDeque* previous; - -} PkDeque; - - -typedef void (*PkTimerCallback)(void *); - -#define PK_TIMER_CALLBACK(callback) void callback(void *) - -struct PkTimer; - -/// The PK timer object - -typedef struct PkTimer { - - /// The time queue management pointers - /// - /// This pointer container is defined as the first element of the - /// structure to allow the PkTimer to be cast to an PkDeque and - /// vice-versa. - PkDeque deque; - - /// The absolute timeout of the timer. - PkTimebase timeout; - - /// The timer callback - /// - /// For PK thread timers used to implement Sleep and semaphore pend - /// timeouts this field is initialized to __pk_thread_timeout(). - PkTimerCallback callback; - - /// Private data passed to the callback. - /// - /// For PK thread timers used to implement Sleep and semaphore pend this - /// field is initialized to a pointer to the thread. - void *arg; - -} PkTimer; - - -// Threads - -typedef void (*PkThreadRoutine)(void *arg); - -#define PK_THREAD_ROUTINE(f) void f(void *arg); - -typedef struct { - - /// Stack pointer saved during context switches. Assembler code expects - /// this to always be at address offset 0 from the thread pointer. - PkAddress saved_stack_pointer; - - /// This is 1 past the last valid byte address of the thread stack. - /// Assembler code expects this to always be at address offset (sizeof - /// PkAddress) from the thread pointer. - PkAddress stack_limit; - - /// This is the original base of the stack. - /// Assembler code expects this to always be at address offset 2 * (sizeof - /// PkAddress) from the thread pointer. - PkAddress stack_base; - - /// If the thread is blocked on a semaphore, then this is the semaphore the - /// thread is blocked on. - PkSemaphore *semaphore; - - /// The thread priority. - PkThreadPriority priority; - - /// The thread state; See \ref pk_thread_states - PkThreadState state; - - /// Thread flags; See \ref pk_thread_flags - PkThreadFlags flags; - - /// The timer structure handles Sleep and blocking on a semaphore with - /// timeout. - PkTimer timer; - -} PkThread; - - -typedef void (*PkBhHandler)(void *); - -#define PK_BH_HANDLER(handler) void handler(void *) - -typedef struct { - - /// The bottom half queue management pointers - /// - /// This pointer container is defined as the first element of the - /// structure to allow the PkBottomHalf to be cast to a PkDeque and - /// vice-versa. - PkDeque deque; - - /// The bottom half handler - PkBhHandler bh_handler; - - /// Private data passed to the handler. - void *arg; - -} PkBottomHalf; - - -// Initialization APIs - -int -pk_initialize(PkAddress kernel_stack, - size_t kernel_stack_size, - PkTimebase initial_timebase, - uint32_t timebase_frequency_hz); - - -// Timebase APIs - -PkTimebase -pk_timebase_get(void); - - -// Timer APIs - -int -pk_timer_create(PkTimer *timer, - PkTimerCallback callback, - void *arg); - - -int -pk_timer_schedule(PkTimer *timer, - PkInterval interval); - -int -pk_timer_cancel(PkTimer *timer); - -int -pk_timer_info_get(PkTimer *timer, - PkTimebase *timeout, - int *active); - -// Thread APIs - -int -pk_thread_create(PkThread *thread, - PkThreadRoutine thread_routine, - void *arg, - PkAddress stack, - size_t stack_size, - PkThreadPriority priority); - -int -pk_start_threads(void); - -int -pk_thread_resume(PkThread *thread); - -int -pk_thread_suspend(PkThread *thread); - -int -pk_thread_delete(PkThread *thread); - -int -pk_complete(void); - -int -pk_sleep(PkInterval interval); - -int -pk_thread_info_get(PkThread *thread, - PkThreadState *state, - PkThreadPriority *priority, - int *runnable); - -int -pk_thread_priority_change(PkThread *thread, - PkThreadPriority new_priority, - PkThreadPriority *old_priority); - -int -pk_thread_at_priority(PkThreadPriority priority, - PkThread **thread); - -int -pk_thread_priority_swap(PkThread* thread_a, PkThread* thread_b); - - -// Semaphore APIs - -int -pk_semaphore_create(PkSemaphore *semaphore, - PkSemaphoreCount initial_count, - PkSemaphoreCount max_count); - -int -pk_semaphore_post(PkSemaphore *semaphore); - -int -pk_semaphore_pend(PkSemaphore *semaphore, - PkInterval timeout); - -int -pk_semaphore_release_all(PkSemaphore *semaphore); - - -int -pk_semaphore_info_get(PkSemaphore *semaphore, - PkSemaphoreCount *count, - int *pending); - -void -pk_semaphore_post_handler(void *arg, - PkIrqId irq); - -// Misc. APIs - -void -pk_halt() __attribute__ ((noreturn)); - -// Deque APIs - -int -pk_deque_sentinel_create(PkDeque *deque); - -#define PK_DEQUE_SENTINEL_INIT(dq_addr) \ -{\ - .next = dq_addr, \ - .previous = dq_addr \ -} - -#define PK_DEQUE_SENTINEL_STATIC_CREATE(deque) \ - PkDeque deque = PK_DEQUE_SENTINEL_INIT(&deque) - -int -pk_deque_element_create(PkDeque *element); - -#define PK_DEQUE_ELEMENT_INIT() \ -{\ - .next = 0, \ - .previous = 0 \ -} - -#define PK_DEQUE_ELEMENT_STATIC_CREATE(deque) \ - PkDeque deque = PK_DEQUE_ELEMENT_INIT() - -/// Check for an empty PkDeque -/// -/// \param deque The sentinel node of a deque -/// -/// \retval 0 The PkDeque is not empty -/// -/// \retval 1 The PkDeque is empty - -static inline int -pk_deque_is_empty(PkDeque *deque) -{ - return (deque == deque->next); -} - - -/// Check if an PkDeque element is currently enqueued -/// -/// \param element Typically the PkDeque object of a queable structure -/// -/// \retval 0 The element is not currently enqueued -/// -/// \retval 1 The element is currently enqueued - -static inline int -pk_deque_is_queued(PkDeque *element) -{ - return (element->next != 0); -} - - -/// Append an element to the tail of a deque (FIFO order) -/// -/// \param deque The sentinel node of a deque -/// -/// \param element Typically the PkDeque object of a queable structure -/// -/// It is an error to call this API on an element that is already enqueued, -/// but the API does not check for this error. - -static inline void -pk_deque_push_back(PkDeque *deque, PkDeque *element) -{ - deque->previous->next = element; - element->previous = deque->previous; - element->next = deque; - deque->previous = element; -} - - -/// Push an element at the head of a deque (LIFO order) -/// -/// \param deque The sentinel node of a deque -/// -/// \param element Typically the PkDeque object of a queable structure -/// -/// It is an error to call this API on an element that is already enqueued, -/// but the API does not check for this error. - -static inline void -pk_deque_push_front(PkDeque *deque, PkDeque *element) -{ - deque->next->previous = element; - element->next = deque->next; - element->previous = deque; - deque->next = element; -} - -/// Pop an element from the head of a deque -/// -/// \param deque The sentinel node of a deque -/// -/// \retval 0 The PkDeque was empty prior to the call -/// -/// \retval non-0 A pointer to the previous head of the deque, which has been -/// removed from the deque and marked as no longer queued. - -// The cast of 'head' is used to remove the 'volatile' attribute. - -static inline PkDeque * -pk_deque_pop_front(PkDeque *deque) -{ - PkDeque *head; - - if (pk_deque_is_empty(deque)) { - return 0; - } else { - head = (PkDeque *)(deque->next); - deque->next = head->next; - deque->next->previous = deque; - head->next = 0; - return head; - } -} - - -/// Remove a deque element from any position in the deque -/// -/// \param element Typically the PkDeque object of a queable structure -/// -/// It is an error to call this API on an element that is not currently -/// enqueued, but the API does not check for this error. - -static inline void -pk_deque_delete(PkDeque *element) -{ - element->previous->next = element->next; - element->next->previous = element->previous; - element->next = 0; -} - -// Bottom Half APIs - -extern PkDeque _pk_bh_queue; - -static inline void -pk_bh_schedule(PkBottomHalf *bottom_half) -{ - pk_deque_push_back(&_pk_bh_queue, (PkDeque *)bottom_half); -} - -#define PK_BH_INIT(_handler, _arg) \ -{\ - .deque = PK_DEQUE_ELEMENT_INIT(), \ - .bh_handler = _handler, \ - .arg = _arg \ -} - -#define PK_BH_STATIC_CREATE(bh_name, handler, arg) \ -PkBottomHalf bh_name = PK_BH_INIT(handler, arg) - - -//Trace function prototypes -void pk_trace_tiny(uint32_t i_parm); -void pk_trace_big(uint32_t i_hash_and_count, - uint64_t i_parm1, uint64_t i_parm2); -void pk_trace_binary(uint32_t i_hash_and_size, void* bufp); -void pk_trace_set_timebase(PkTimebase timebase); - - -/// Cast a pointer to another type, in a way that won't cause warnings - -#define PK_CAST_POINTER(t, p) ((t)((PkAddress)(p))) - -// Static Assert Macro for Compile time assertions. -// - This macro can be used both inside and outside of a function. -// - A value of false will cause the ASSERT to produce this error -// - This will show up on a compile fail as: -// : error: size of array '_static_assert' is negative -// - It would be trivial to use the macro to paste a more descriptive -// array name for each assert, but we will leave it like this for now. -#define PK_STATIC_ASSERT(cond) extern uint8_t _static_assert[(cond) ? 1 : -1] __attribute__ ((unused)) - -/// \page pk_errors PK API and Kernel Error Handling -/// -/// Error checking in the PK API consumes a significant amount of code space. -/// Approximately 20% of the object code in the PPC405 port is devoted to -/// error checking. Presumably a like amount of time overhead is also added to -/// PK API calls by this checking. -/// -/// API error checking can be disabled to save space and time in the kernel. -/// API errors can also be configured to cause kernel panics, allowing -/// applications to be coded without the overhead of error checking but still -/// providing an escape in the event of application errors or (unlikely) -/// hardware failures. The PK default is to check for API errors and kernel -/// invariants, and panic should errors occur. -/// -/// PK follows the Unix convention that a successful call of an API returns 0 -/// (PK_OK), but returns a negative code in the event of failure, or to -/// provide further information. The error codes are all defined as manifest -/// constants. -/// -/// Some negative codes returned by PK APIs are not considered errors. These -/// conditions are always checked, never cause a panic if they occur, and -/// their interpretation is always left to the application. See the detailed -/// documentation for each API for lists of error and non-error codes returned -/// by the API. -/// -/// There are three configuration options that control error handling in the -/// PK API and kernel: -/// -/// \c PK_ERROR_CHECK_API -/// -/// \arg \b 0 - No PK API error checking. APIs that potentially return error -/// codes will always return 0 (PK_OK) instead of an error code. Those -/// APIs that return negative codes that are not errors (see Table 1.5) -/// always return the negative non-error codes when appropriate. -/// -/// \arg \b 1 - (Default) All PK API errors are checked. The behavior in -/// the event of an error is defined by the configuration option -/// PK_ERROR_PANIC. -/// -/// \c PK_ERROR_CHECK_KERNEL -/// -/// \arg \b 0 - No kernel invariant error checking is done. -/// -/// \arg \b 1 - (Default) Selected kernel invariants are checked. The overhead -/// for these checks should be minimal. -/// -/// \c PK_ERROR_PANIC -/// -/// \arg \b 0 - PK API calls return negative error codes in the event of -/// errors. Note that PK kernel invariants always cause a panic if -/// violations occur. -/// -/// \arg \b 1 - (Default) In the event of errors PK APIs invoke PK_PANIC(code), -/// where code is a positive error code. Kernel invariant checks always -/// cause a panic if violations are detected. - -#endif /* __ASSEMBLER__ */ - -#endif /* __PK_API_H__ */ diff --git a/pk/kernel/pk_bh_core.c b/pk/kernel/pk_bh_core.c deleted file mode 100644 index 8a6181cb..00000000 --- a/pk/kernel/pk_bh_core.c +++ /dev/null @@ -1,29 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2015 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_bh_core.c -/// \brief PK bottom half APIs -/// -/// The entry points in this file are considered 'core' routines that will -/// always be present at runtime in any PK application. - -#include "pk.h" - -/// Statically initialize the bottom half queue -PK_DEQUE_SENTINEL_STATIC_CREATE(_pk_bh_queue); - -void _pk_process_bh(void) -{ - PkBottomHalf *bh; - while((bh = (PkBottomHalf*)pk_deque_pop_front(&_pk_bh_queue)) != 0) - { - bh->bh_handler(bh->arg); - } - return; -} - - -#undef __PK_THREAD_CORE_C__ diff --git a/pk/kernel/pk_core.c b/pk/kernel/pk_core.c deleted file mode 100644 index bfa6d6be..00000000 --- a/pk/kernel/pk_core.c +++ /dev/null @@ -1,79 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_core.c -/// \brief Core routines for the PK kernel. -/// -/// The entry points in this file are routines that are expected to be needed -/// at runtime by all PK applications. This file also serves as a place for -/// kernel global variables to be realized. - -#define __PK_CORE_C__ - -#include "pk.h" - -#if !PK_TIMER_SUPPORT - -/// If there is no timer support, then any call of the timer interrupt handler -/// is considered a fatal error. - -void -__pk_timer_handler() -{ - PK_PANIC(PK_NO_TIMER_SUPPORT); -} - -#endif /* PK_TIMER_SUPPORT */ - - -/// Initialize an PkDeque sentinel node -/// -/// \param deque The sentinel node of the deque -/// -/// PK has no way of knowing whether the \a deque is currently in use, so -/// this API must only be called on unitialized or otherwise unused sentinel -/// nodes. -/// -/// \retval 0 success -/// -/// \retval -PK_INVALID_DEQUE_SENTINEL The \a deque pointer was null - -int -pk_deque_sentinel_create(PkDeque *deque) -{ - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(deque == 0, PK_INVALID_DEQUE_SENTINEL); - } - - deque->next = deque->previous = deque; - return 0; -} - - -/// Initialize an PkDeque element -/// -/// \param element Typically the PkDeque object of a queable structure -/// -/// PK has no way of knowing whether the \a element is currently in use, so -/// this API must only be called on unitialized or otherwise unused deque -/// elements. -/// -/// \retval 0 success -/// -/// \retval -PK_INVALID_DEQUE_ELEMENT The \a element pointer was null - -int -pk_deque_element_create(PkDeque *element) -{ - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(element == 0, PK_INVALID_DEQUE_ELEMENT); - } - - element->next = 0; - return 0; -} - -#undef __PK_CORE_C__ diff --git a/pk/kernel/pk_debug_ptrs.c b/pk/kernel/pk_debug_ptrs.c deleted file mode 100644 index 0ed540f4..00000000 --- a/pk/kernel/pk_debug_ptrs.c +++ /dev/null @@ -1,53 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2015 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_debug_ptrs.c -/// \brief Defines a table of pointers to important kernel debug data. -/// -/// This table is placed in a special section named .debug_ptrs which can be -/// placed at a well-known memory location for tools to find. -/// - -#include "pk.h" -#include "pk_trace.h" -#include "pk_debug_ptrs.h" - -extern PkTimebase ppe42_64bit_timebase; - -#if PK_TRACE_SUPPORT -extern PkTraceBuffer g_pk_trace_buf; -#endif - -pk_debug_ptrs_t pk_debug_ptrs SECTION_ATTRIBUTE(".debug_ptrs") = -{ - .debug_ptrs_size = sizeof(pk_debug_ptrs), - .debug_ptrs_version = PK_DEBUG_PTRS_VERSION, - -#if PK_TRACE_SUPPORT - .debug_trace_ptr = &g_pk_trace_buf, - .debug_trace_size = sizeof(g_pk_trace_buf), -#else - .debug_trace_ptr = 0, - .debug_trace_size = 0, -#endif /* PK_TRACE_SUPPORT */ - -#if PK_THREAD_SUPPORT - .debug_thread_table_ptr = &__pk_priority_map, - .debug_thread_table_size = sizeof(__pk_priority_map), - .debug_thread_runq_ptr = (void*)&__pk_run_queue, - .debug_thread_runq_size = sizeof(__pk_run_queue), -#else - .debug_thread_table_ptr = 0, - .debug_thread_table_size = 0, - .debug_thread_runq_ptr = 0, - .debug_thread_runq_size = 0, -#endif /* PK_THREAD_SUPPORT */ - - .debug_timebase_ptr = &ppe42_64bit_timebase, - .debug_timebase_size = sizeof(ppe42_64bit_timebase), - -}; - diff --git a/pk/kernel/pk_debug_ptrs.h b/pk/kernel/pk_debug_ptrs.h deleted file mode 100644 index 62a36839..00000000 --- a/pk/kernel/pk_debug_ptrs.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef __PK_DEBUG_PTRS_H__ -#define __PK_DEBUG_PTRS_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2015 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_debug_ptrs.h -/// \brief Structure for a table of pointers to kernel debug data -/// - -#define PK_DEBUG_PTRS_VERSION 1 - -typedef struct -{ - // The size and version of this structure - unsigned short debug_ptrs_size; - unsigned short debug_ptrs_version; - - // Trace buffer location and size - void* debug_trace_ptr; - unsigned long debug_trace_size; - - // Thread table location and size - void* debug_thread_table_ptr; - unsigned long debug_thread_table_size; - - // Thread run queue location and size - void* debug_thread_runq_ptr; - unsigned long debug_thread_runq_size; - - // Emulated timebase location and size - void* debug_timebase_ptr; - unsigned long debug_timebase_size; - -} pk_debug_ptrs_t; - -#endif /*__PK_DEBUG_PTRS_H__*/ diff --git a/pk/kernel/pk_init.c b/pk/kernel/pk_init.c deleted file mode 100644 index ebd6323a..00000000 --- a/pk/kernel/pk_init.c +++ /dev/null @@ -1,196 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_init.c -/// \brief PK initialization -/// -/// The entry points in this file are initialization routines - they are never -/// needed after PK initialization and their code space could be reclaimed by -/// the application after initialization if required. - -#include "pk.h" -#include "pk_trace.h" - -uint32_t __pk_timebase_frequency_hz; - -/// The timebase frequency is passed into PK during initialization. It cannot -/// be set statically because there is a requirement to support a frequency -/// that can change from one IPL to the next. On the 405, scaling of time -/// intervals is accomplished by doing a 32x32 bit multiplication which is -/// supported by the ppc405 instruction set. PPE42 does not support 32x32 bit -/// multiplication directly and some applications can not afford to use a -/// function call to emulate the operation. Instead we scale the time -/// interval by shifting the value X bits to the right and adding it to itself. -/// This can scale the value by 2, 1.5, 1.25, 1.125, etc. -/// -/// This is the right shift value. -/// NOTE: shifting by 0 gives a 2x scale factor, shifting by 32 gives a 1x -/// scale factor. -uint8_t __pk_timebase_rshift = 32; - -void pk_set_timebase_rshift(uint32_t timebase_freq_hz) -{ - //Use 1.0 scale if less than halfway between 1.0 and 1.25 - if(timebase_freq_hz <= (PK_BASE_FREQ_HZ + (PK_BASE_FREQ_HZ >> 3))) - { - __pk_timebase_rshift = 32; - } - - //use 1.25 scale if less than halfway between 1.25 and 1.5 - else if(timebase_freq_hz <= (PK_BASE_FREQ_HZ + (PK_BASE_FREQ_HZ >> 3) + (PK_BASE_FREQ_HZ >> 2))) - { - __pk_timebase_rshift = 2; - } - //use 1.5 scale if less than halfway between 1.5 and 2.0 - else if(timebase_freq_hz <= (PK_BASE_FREQ_HZ + (PK_BASE_FREQ_HZ >> 2) + (PK_BASE_FREQ_HZ >> 1))) - { - __pk_timebase_rshift = 1; - } - //use 2.0 scale if greater than 1.5 - else - { - __pk_timebase_rshift = 0; - } -} - -/// Initialize PK. -/// -/// \param kernel_stack A stack area for interrupt and bottom-half handlers. -/// -/// \param kernel_stack_size The size (in bytes) of the stack area for -/// interrupt and bottom-half handlers. -/// -/// \param initial_timebase The initial value of the PK timebase. -/// If the argument is given as the special value \c PK_TIMEBASE_CONTINUES, then the -/// timebase is not reset. -/// -/// \param timebase_frequency_hz The frequency of the PK timebase in Hz. -/// -/// This routine \e must be called before any other PK / routines, and \e -/// should be called before any interrupts are enabled. -/// -/// Return values other than PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_ARGUMENT_INIT A stack pointer is 0 or is given -/// a 0 size. -/// -/// \retval -PK_STACK_OVERFLOW One or both stacks are not large enough to -/// support a minimum context save in the event of an interrupt. - -// Note that PK does not rely on any static initialization of dynamic -// variables. In debugging sessions using RAM-resident PK images it is -// assumed that the processor may be reset at any time, so we always need to -// reset everything at initialization. - -int -pk_initialize(PkAddress kernel_stack, - size_t kernel_stack_size, - PkTimebase initial_timebase, - uint32_t timebase_frequency_hz) -{ - int rc; - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF((kernel_stack == 0) || - (kernel_stack_size == 0), - PK_INVALID_ARGUMENT_INIT); - } - - __pk_timebase_frequency_hz = timebase_frequency_hz; - - __pk_thread_machine_context_default = PK_THREAD_MACHINE_CONTEXT_DEFAULT; - - rc = __pk_stack_init(&kernel_stack, &kernel_stack_size); - if (rc) { - return rc; - } - - __pk_kernel_stack = kernel_stack; - __pk_kernel_stack_size = kernel_stack_size; - -#if PK_TIMER_SUPPORT - - // Initialize the time queue sentinel as a circular queue, set the next - // timeout and clear the cursor. - - pk_deque_sentinel_create((PkDeque*)&__pk_time_queue); - __pk_time_queue.cursor = 0; - __pk_time_queue.next_timeout = PK_TIMEBASE_MAX; - -#if PK_TRACE_SUPPORT -extern PkTimer g_pk_trace_timer; -extern PkTraceBuffer g_pk_trace_buf; - - //set the trace timebase HZ - g_pk_trace_buf.hz = timebase_frequency_hz; - - //set the shift adjustment to get us closer to the true - //timebase frequency (versus what was hardcoded) - pk_set_timebase_rshift(timebase_frequency_hz); - - if(initial_timebase != PK_TIMEBASE_CONTINUES) - { - //set the timebase ajdustment for trace synchronization - pk_trace_set_timebase(initial_timebase); - } - - // Schedule the timer that puts a 64bit timestamp in the trace buffer - // periodically. This allows us to use 32bit timestamps. - pk_timer_schedule(&g_pk_trace_timer, - PK_TRACE_TIMER_PERIOD); - -#endif /* PK_TRACE_SUPPORT */ - -#endif /* PK_TIMER_SUPPORT */ - -#if PK_THREAD_SUPPORT - - // Clear the priority map. The final entry [PK_THREADS] is for the idle - // thread. - - int i; - for (i = 0; i <= PK_THREADS; i++) { - __pk_priority_map[i] = 0; - } - - // Initialize the thread scheduler - - __pk_thread_queue_clear(&__pk_run_queue); - __pk_current_thread = 0; - __pk_next_thread = 0; - __pk_delayed_switch = 0; - -#endif /* PK_THREAD_SUPPORT */ - - return PK_OK; -} - - -/// Call the application main() -/// -/// __pk_main() is called from the bootloader. It's only purpose is to -/// provide a place for the PK_MAIN_HOOK to be called before main() is -/// called. - -void -__pk_main(int argc, char **argv) -{ - PK_MAIN_HOOK; - - int main(int argc, char **argv); - main(argc, argv); -} - - - - - - - - - diff --git a/pk/kernel/pk_kernel.h b/pk/kernel/pk_kernel.h deleted file mode 100644 index 85b028a2..00000000 --- a/pk/kernel/pk_kernel.h +++ /dev/null @@ -1,246 +0,0 @@ -#ifndef __PK_KERNEL_H__ -#define __PK_KERNEL_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_kernel.h -/// \brief PK portable kernel (non-API) data and data structures -/// -/// \todo In theory, as long as the critical section entry/exit macros use GCC -/// memory barriers, we should be able to eliminate all of the 'volatile' -/// declarations in PK code. These have been added to the port, so -/// we should try it. - -#ifdef __PK_CORE_C__ -#define IF__PK_CORE_C__(x) x -#define UNLESS__PK_CORE_C__(x) -#else -#define IF__PK_CORE_C__(x) -#define UNLESS__PK_CORE_C__(x) x -#endif - -#if PK_MINIMIZE_KERNEL_CODE_SPACE -#define IF_PK_MINIMIZE_KERNEL_CODE_SPACE(x) x -#define UNLESS_PK_MINIMIZE_KERNEL_CODE_SPACE(x) -#else -#define IF_PK_MINIMIZE_KERNEL_CODE_SPACE(x) -#define UNLESS_PK_MINIMIZE_KERNEL_CODE_SPACE(x) x -#endif - - -#ifndef __ASSEMBLER__ - -/// This is the stack pointer saved when switching from a thread context to an -/// interrupt context. - -UNLESS__PK_CORE_C__(extern) -volatile -PkAddress __pk_saved_sp; - -/// The kernel stack; constant once defined by the call of -/// pk_initialize(). - -UNLESS__PK_CORE_C__(extern) -volatile -PkAddress __pk_kernel_stack; - -/// This is the run queue - the queue of mapped runnable tasks. -UNLESS__PK_CORE_C__(extern) -volatile -PkThreadQueue __pk_run_queue; - -/// This flag is set by \c __pk_schedule() if a new highest-priority thread -/// becomes runnable during an interrupt handler. The context switch will -/// take place at the end of interrupt processing, and the -/// interrupt handling code will clear the flag. - -UNLESS__PK_CORE_C__(extern) -volatile -int __pk_delayed_switch; - -/// The currently running thread, or NULL (0) to indicate the idle thread -/// -/// \a __pk_current_thread holds a pointer to the currently executing -/// thread. This pointer will be NULL (0) under the following conditions: -/// -/// - After pk_initialize() but prior to pk_start_threads() -/// -/// - After pk_start_threads(), when no threads are runnable. In this case -/// the NULL (0) value indicates that the PK idle thread is 'running'. -/// -/// - After pk_start_threads(), when the current (non-idle) thread has -/// completed or been deleted. -/// -/// If \a __pk_current_thread == 0 then there is no requirement to save any -/// register state on a context switch, either because the PK idle thread has -/// no permanent context, or because any thread context on the kernel stack is -/// associated with a deleted thread. -/// -/// If \a __pk_current_thread != 0 then \a __pk_current_thread is a pointer -/// to the currently executing thread. In an interrupt handler \a -/// pk_current_thread is a pointer to the thread whose context is saved on -/// the kernel stack. -UNLESS__PK_CORE_C__(extern) -volatile -PkThread* __pk_current_thread; - -/// The thread to switch to during the next context switch, or NULL (0). -/// -/// \a __pk_next_thread is computed by __pk_schedule(). \a -/// __pk_next_thread holds a pointer to the thread to switch to at the next -/// context switch. In a thread context the switch happens immediately if \a -/// __pk_next_thread == 0 or \a __pk_next_thread != \a __pk_current_thread. -/// In an interrupt context the check happens at the end of processing all -/// interrupts. -/// -/// \a __pk_next_thread may be NULL (0) under the following -/// conditions: -/// -/// - After pk_initialize() but prior to pk_start_threads(), assuming no -/// threads have been made runnable. -/// -/// - After pk_start_threads(), when no threads are runnable. In this case -/// the NULL (0) value indicates that the PK idle thread is the next thread -/// to 'run'. -/// -/// If \a __pk_next_thread == 0 then there is no requirement to restore -/// any register state on a context switch, because the PK idle thread has -/// no permanent context. -/// -/// If \a __pk_next_thread != 0 then \a __pk_next_thread is a pointer -/// to the thread whose context will be restored at the next context switch. -UNLESS__PK_CORE_C__(extern) -volatile -PkThread* __pk_next_thread; - -/// The priority of \a __pk_next_thread -/// -/// If \a __pk_next_thread == 0, the \a __pk_next_priority == PK_THREADS. -UNLESS__PK_CORE_C__(extern) -volatile -PkThreadPriority __pk_next_priority; - -/// This variable holds the default thread machine context for newly created -/// threads. The idle thread also uses this context. This variable is normally -/// constant after the call of \c pk_initialize(). - -UNLESS__PK_CORE_C__(extern) -volatile -PkMachineContext __pk_thread_machine_context_default; - - -/// The size of the kernel stack (bytes). - -UNLESS__PK_CORE_C__(extern) -volatile -size_t __pk_kernel_stack_size; - -/// This table maps priorities to threads, and contains PK_THREADS + 1 -/// entries. The final entry is for the idle thread and will always be null -/// after initizlization. - -UNLESS__PK_CORE_C__(extern) -volatile -PkThread* __pk_priority_map[PK_THREADS + 1]; - -/// The PK time queue structure -/// -/// This structure is defined for use by the kernel, however applications -/// could also use this structure to define their own time queues. - -typedef struct { - - /// A sentinel node for the time queue. - /// - /// The time queue is an PkDeque managed as a FIFO queue for queue - /// management purpose, although events time out in time order. - /// - /// This pointer container is defined as the first element of the - /// structure to allow the PkTimeQueue to be cast to an PkDeque. - PkDeque queue; - - /// The next timeout in absolute time. - PkTimebase next_timeout; - - /// A pointer to allow preemption of time queue processing - /// - /// If non-0, then this is the next timer in the time queue to handle, or - /// a pointer to the \a queue object indicating no more timers to handle. - /// - /// \a cursor != 0 implies that time queue handler is in the midst of - /// processing the time queue, but has enabled interrupt preemption for - /// processing a timer handler. This means that 1) if the timer pointed to - /// by \a cursor is deleted then the cursor must be assigned to the - /// next timer in the queue; and 2) if a new timer is scheduled then - /// activating the next timeout will be handled by the timer handler. - PkDeque* cursor; - -} PkTimeQueue; - -UNLESS__PK_CORE_C__(extern) -PkTimeQueue __pk_time_queue; - -/// Return a pointer to the PkThread object of the currently running thread, -/// or NULL (0) if PK is idle or has not been started. -/// -/// In this API the current thread is not volatile - it will never change -/// inside application code - thus the 'volatile' is cast away. The PK kernel -/// does not (must not) use this API. - -UNLESS__PK_CORE_C__(extern) -inline PkThread * -pk_current(void) -{ - return (PkThread *)__pk_current_thread; -} - -/// Schedule the next timeout in a machine-specific way. - -void -__pk_schedule_hardware_timeout(PkTimebase timeout); - -/// The thread timeout handler. Portable. - -PK_TIMER_CALLBACK(__pk_thread_timeout); - -/// Generic stack initialization. Portable. - -int -__pk_stack_init(PkAddress *stack, - size_t *size); - -/// Machine-specific thread context initialization. - -void -__pk_thread_context_initialize(PkThread *thread, - PkThreadRoutine thread_routine, - void *arg); - -/// Machine specific resumption of __pk_next_thread at __pk_next_priority -/// without saving the current context. -void -__pk_next_thread_resume(void); - -/// Schedule a timer in the time queue. Portable. -void -__pk_timer_schedule(PkTimer *timer); - -/// Remove a timer from the time queue. Portable. -int -__pk_timer_cancel(PkTimer *timer); - -void -__pk_schedule(void); - - -// Call the application main(). Portable. - -void -__pk_main(int argc, char **argv); - -#endif /* __ASSEMBLER__ */ - -#endif /* __PK_KERNEL_H__ */ diff --git a/pk/kernel/pk_macros.h b/pk/kernel/pk_macros.h deleted file mode 100644 index 45bfbac6..00000000 --- a/pk/kernel/pk_macros.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef __PK_MACROS_H__ -#define __PK_MACROS_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_macros.h -/// \brief Boilerplate macros for PK - -/// This macro encapsulates error handling boilerplate for code that uses the -/// PK API-type error handling, for errors that do not occur in critical -/// sections. - -#define PK_ERROR(code) \ - do { \ - if (PK_ERROR_PANIC) { \ - PK_PANIC(code); \ - } else { \ - return -(code); \ - } \ - } while (0) - - -/// This macro encapsulates error handling boilerplate in the PK API -/// functions, for errors that do not occur in critical sections. - -#define PK_ERROR_IF(condition, code) \ - do { \ - if (condition) { \ - PK_ERROR(code); \ - } \ - } while (0) - - -/// This macro encapsulates error handling boilerplate in the PK API -/// functions, for errors that do not occur in critical sections and always -/// force a kernel panic, indicating a kernel or API bug. - -#define PK_PANIC_IF(condition, code) \ - do { \ - if (condition) { \ - PK_PANIC(code); \ - } \ - } while (0) - - -/// This macro encapsulates error handling boilerplate in the PK API -/// functions, for errors that do not occur in critical sections. -/// The error handling will only be enabled when PK_ERROR_CHECK_API -/// is enabled. - -#define PK_ERROR_IF_CHECK_API(condition, code) \ - do { \ - if (PK_ERROR_CHECK_API) { \ - PK_ERROR_IF(condition, code); \ - } \ - } while (0) - -/// This macro encapsulates error handling boilerplate in the PK API -/// functions, for errors that occur in critical sections. - -#define PK_ERROR_IF_CRITICAL(condition, code, context) \ - do { \ - if (condition) { \ - if (PK_ERROR_PANIC) { \ - PK_PANIC(code); \ - pk_critical_section_exit(context); \ - } else { \ - pk_critical_section_exit(context); \ - return -(code); \ - } \ - } \ - } while (0) - - -/// This is a general macro for errors that require cleanup before returning -/// the error code. - -#define PK_ERROR_IF_CLEANUP(condition, code, cleanup) \ - do { \ - if (condition) { \ - if (PK_ERROR_PANIC) { \ - PK_PANIC(code); \ - cleanup; \ - } else { \ - cleanup; \ - return -(code); \ - } \ - } \ - } while (0) - - - -/// Some PK APIs can only be called from thread contexts - these are APIs -/// that threads call on 'themselves'. - -#define PK_ERROR_UNLESS_THREAD_CONTEXT() \ - PK_ERROR_IF(!__pk_kernel_context_thread(), \ - PK_ILLEGAL_CONTEXT_THREAD_CONTEXT) - - -/// Some PK APIs must be called from an interrupt context only. - -#define PK_ERROR_UNLESS_ANY_INTERRUPT_CONTEXT() \ - PK_ERROR_IF(!__pk_kernel_context_any_interrupt(), \ - PK_ILLEGAL_CONTEXT_INTERRUPT_CONTEXT) - -#endif /* __PK_MACROS_H__ */ diff --git a/pk/kernel/pk_semaphore_core.c b/pk/kernel/pk_semaphore_core.c deleted file mode 100644 index 0e1e34d4..00000000 --- a/pk/kernel/pk_semaphore_core.c +++ /dev/null @@ -1,318 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_semaphore_core.c -/// \brief PK semaphore APIs -/// -/// The entry points in this file are considered 'core' routines that will -/// always be present at runtime in any PK application that enables -/// semaphores. - -#include "pk.h" - -/// Post a count to a semaphore -/// -/// \param semaphore A pointer to the semaphore -/// -/// If any thread is pending on the semaphore, the highest priority thread -/// will be made runnable and the internal count will remain 0. -/// -/// If no thread is pending on the semaphore then the internal count will be -/// incremented by 1, with overflow wrapping the internal count through 0. If -/// the \a max_count argument supplied when the semaphore was created is -/// non-zero and the new internal count is greater than the \a max_count, an -/// overflow error will be signalled. -/// -/// Return values other than PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_SEMAPHORE_AT_POST The \a semaphore is a null (0) pointer. -/// -/// \retval -PK_SEMAPHORE_OVERFLOW The \a max_count argument supplied when -/// the semaphore was created is non-zero and the new internal count is -/// greater than the \a max_count. - -int -pk_semaphore_post(PkSemaphore *semaphore) -{ - PkMachineContext ctx; - PkThreadPriority priority; - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(semaphore == 0, PK_INVALID_SEMAPHORE_AT_POST); - } - - pk_critical_section_enter(&ctx); - - priority = __pk_thread_queue_min(&(semaphore->pending_threads)); - - if (priority != PK_IDLE_THREAD_PRIORITY) { - - __pk_thread_queue_delete(&(semaphore->pending_threads), priority); - __pk_thread_queue_insert(&__pk_run_queue, priority); - - PK_KERN_TRACE("THREAD_SEMAPHORE_POST(%d)", priority); - - __pk_schedule(); - - } else { - - semaphore->count++; - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF((semaphore->max_count > 0) && - (semaphore->count > semaphore->max_count), - PK_SEMAPHORE_OVERFLOW); - } - } - - pk_critical_section_exit(&ctx); - - return PK_OK; -} - - -/// Pend on a semaphore with timeout -/// -/// \param semaphore A pointer to the semaphore -/// -/// \param timeout A relative timeout in PK timebase ticks, including the -/// special values PK_NO_WAIT and PK_WAIT_FOREVER -/// -/// This API is normally called from threads, and can only be successfully -/// called from interupt handlers under special conditions. -/// -/// If the internal count of the \a semaphore is non-zero, the internal count -/// is decremented by one and execution of the caller continues. -/// -/// If the internal count of the \a semaphore is zero and the \a timeout is -/// PK_NO_WAIT (0) then the call returns immediately with the informational -/// code -PK_SEMAPHORE_PEND_NO_WAIT. -/// -/// If the internal count of the \a semaphore is zero and the \a timeout is -/// non-zero then a thread will block until either a semaphore count is -/// acquired or the relative timeout expires. If this condition occurs in a -/// call from an interrupt context or before threads have been started then -/// the call will fail with the error \c -PK_SEMAPHORE_PEND_WOULD_BLOCK. -/// -/// Once timed out the thread is removed from the semaphore pending queue and -/// made runnable, and the pk_semaphore_pend() operation will fail, even if -/// the semaphore count becomes available before the thread runs again. The -/// pk_semaphore_pend() API returns the informational code -/// -PK_SEMAPHORE_PEND_TIMED_OUT in this case. -/// -/// By convention, a timeout interval equal to the maximum possible value of -/// the \c PkInterval type is taken to mean "wait forever". A thread blocked -/// on a semaphore in this mode will never time out. PK provides this -/// constant as \c PK_WAIT_FOREVER. -/// -/// Return values other than PK_OK (0) are not necessarily errors; see \ref -/// pk_errors -/// -/// The following return codes are non-error codes: -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_SEMAPHORE_PEND_NO_WAIT timeout is set to PK_NO_WAIT -/// -/// \retval -PK_SEMAPHORE_PEND_TIMED_OUT The semaphore was not acquired -/// before the timeout expired. -/// -/// The following return codes are error codes: -/// -/// \retval -PK_INVALID_SEMAPHORE_AT_PEND The \a semaphore is a null (0) -/// pointer. -/// -/// \retval -PK_SEMAPHORE_PEND_WOULD_BLOCK The call was made from an -/// interrupt context (or before threads have been started), the semaphore -/// internal count was 0 and a non-zero timeout was specified. - -// Note: Casting __pk_current_thread removes the 'volatile' attribute. - -int -pk_semaphore_pend(PkSemaphore *semaphore, - PkInterval timeout) -{ - PkMachineContext ctx; - PkThreadPriority priority; - PkThread *thread; - PkTimer *timer = 0; - PkInterval scaled_timeout = PK_INTERVAL_SCALE(timeout); - - int rc = PK_OK; - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(semaphore == 0, PK_INVALID_SEMAPHORE_AT_PEND); - } - - pk_critical_section_enter(&ctx); - - if (semaphore->count != 0) { - - semaphore->count--; - - } else if (timeout == PK_NO_WAIT) { - - rc = -PK_SEMAPHORE_PEND_NO_WAIT; - - } else { - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF_CRITICAL(!__pk_kernel_context_thread(), - PK_SEMAPHORE_PEND_WOULD_BLOCK, - &ctx); - } - - thread = (PkThread *)__pk_current_thread; - priority = thread->priority; - - __pk_thread_queue_insert(&(semaphore->pending_threads), priority); - - thread->semaphore = semaphore; - thread->flags |= PK_THREAD_FLAG_SEMAPHORE_PEND; - - PK_KERN_TRACE("THREAD_SEMAPHORE_PEND(%d)", priority); - - if (timeout != PK_WAIT_FOREVER) { - timer = &(thread->timer); - timer->timeout = pk_timebase_get() + scaled_timeout; - __pk_timer_schedule(timer); - thread->flags |= PK_THREAD_FLAG_TIMER_PEND; - } - - __pk_thread_queue_delete(&__pk_run_queue, priority); - __pk_schedule(); - - thread->flags &= ~PK_THREAD_FLAG_SEMAPHORE_PEND; - - if (thread->flags & PK_THREAD_FLAG_TIMER_PEND) { - if (thread->flags & PK_THREAD_FLAG_TIMED_OUT) { - rc = -PK_SEMAPHORE_PEND_TIMED_OUT; - __pk_thread_queue_delete(&(semaphore->pending_threads), thread->priority); - } else { - __pk_timer_cancel(timer); - } - thread->flags &= - ~(PK_THREAD_FLAG_TIMER_PEND | PK_THREAD_FLAG_TIMED_OUT); - } - } - - pk_critical_section_exit(&ctx); - - return rc; -} - - -/// Release all threads blocked on a semaphore -/// -/// \param semaphore A pointer to a semaphore -/// -/// This API is provided to allow an PK semaphore to be used as a thread -/// barrier. pk_semaphore_release_all() simultaneously unblocks all threads -/// (if any) currently pending on a semaphore. A semaphore to be used as a -/// thread barrier will typically be initialized with -/// pk_semaphore_create(\a sem, 0, 0), and sxx_semaphore_post() would never be -/// called on the \a sem. -/// -/// This API never modifies the \a count field of the semaphore; If any -/// threads are blocked on a semaphore the semaphore count is 0 by definition. -/// -/// Return values other than PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_SEMAPHORE_AT_RELEASE The \a semaphore is a null (0) -/// pointer. - -int -pk_semaphore_release_all(PkSemaphore* semaphore) -{ - PkMachineContext ctx; - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(semaphore == 0, PK_INVALID_SEMAPHORE_AT_RELEASE); - } - - pk_critical_section_enter(&ctx); - - __pk_thread_queue_union(&__pk_run_queue, &(semaphore->pending_threads)); - __pk_thread_queue_clear(&(semaphore->pending_threads)); - __pk_schedule(); - - pk_critical_section_exit(&ctx); - - return PK_OK; -} - - -/// Get information about a semaphore. -/// -/// \param semaphore A pointer to the PkSemaphore to query -/// -/// \param count The value returned through this pointer is the current count -/// of the semaphore. The caller can set this parameter to the null pointer -/// (0) if this information is not required. -/// -/// \param pending The value returned through this pointer is the current -/// number of threads pending on the semaphore. The caller can set this -/// parameter to the null pointer (0) if this information is not required. -/// -/// The information returned by this API can only be guaranteed consistent if -/// the API is called from a critical section. -/// -/// Return values other than PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_SEMAPHORE_AT_INFO The \a semaphore is a null (0) -/// pointer. - -int -pk_semaphore_info_get(PkSemaphore* semaphore, - PkSemaphoreCount* count, - int* pending) - -{ - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(semaphore == 0, PK_INVALID_SEMAPHORE_AT_INFO); - } - - if (count) { - *count = semaphore->count; - } - if (pending) { - *pending = __pk_thread_queue_count(&(semaphore->pending_threads)); - } - - return PK_OK; -} - - -/// An simple interrupt handler that posts to a semaphore. -/// -/// To implement basic event-driven blocking of a thread, install -/// pk_semaphore_post_handler() as the handler for an interrupt -/// and provide a pointer to the semaphore as the \a arg argument in -/// pk_irq_handler_set(). The semaphore should be initialized with -/// pk_semaphore_create(&sem, 0, 1). This handler simply disables (masks) -/// the interrupt, clears the status and calls pk_semaphore_post() on the -/// semaphore. -/// -/// Note that clearing the status in the interrupt controller as done here is -/// effectively a no-op for level-sensitive interrupts. In the level-sensitive -/// case any thread pending on the semaphore must reset the interrupt -/// condition in the device before re-enabling the interrupt. -#if 0 -void -pk_semaphore_post_handler(void *arg, PkIrqId irq, int priority) -{ - pk_irq_disable(irq); - pk_irq_status_clear(irq); - pk_semaphore_post((PkSemaphore *)arg); -} - -#endif diff --git a/pk/kernel/pk_semaphore_init.c b/pk/kernel/pk_semaphore_init.c deleted file mode 100644 index bed029da..00000000 --- a/pk/kernel/pk_semaphore_init.c +++ /dev/null @@ -1,82 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_semaphore_init.c -/// \brief PK semaphore API initialization routines -/// -/// The entry points in this file are routines that are typically used during -/// initialization, and their code space could be deallocated and recovered if -/// no longer needed by the application after initialization. - -#include "pk.h" - -/// Create (initialize) a semaphore -/// -/// \param semaphore A pointer to an PkSemaphore structure to initialize -/// -/// \param initial_count The initial count of the semaphore -/// -/// \param max_count The maximum count allowed in the semaphore, for error -/// checking -/// -/// Semaphores are created (initialized) by a call of \c -/// pk_semaphore_create(), using an application-provided instance of an \c -/// PkSemaphore structure. This structure \e is the semaphore, so the -/// application must never modify the structure if the semaphore is in use. -/// PK has no way to know if an \c PkSemaphore structure provided to -/// \c pk_semaphore_create() is safe to use as a semaphore, and will silently -/// modify whatever memory is provided. -/// -/// PK provides two simple overflow semantics based on the value of max_count -/// in the call of \c pk_semaphore_create(). -/// -/// If \a max_count = 0, then posting to the semaphore first increments the -/// internal count by 1. Overflows are ignored and will wrap the internal -/// count through 0. -/// -/// If \a max_count != 0, then posting to the semaphore first increments the -/// internal count by 1, wrapping through 0 in the event of overflow. If the -/// resulting count is greater than max_count, \c pk_semaphore_post() will -/// return the error \c -PK_SEMAPHORE_POST_OVERFLOW to the caller. -/// -/// In most applications it is probably best to use the \a max_count != 0 -/// semantics to trap programming errors, unless there is a specific -/// application where overflow is expected and ignorable. As a fine point of -/// the specification, a \a max_count of 0 is equivalent to a max_count of -/// 0xFFFFFFFF. -/// -/// Return values other then PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_SEMAPHORE_AT_CREATE The \a semaphore is a null (0) -/// pointer. -/// -/// \retval -PK_INVALID_ARGUMENT_SEMAPHORE The \a max_count is non-zero -/// and less than the \a initial_count. - -int -pk_semaphore_create(PkSemaphore *semaphore, - PkSemaphoreCount initial_count, - PkSemaphoreCount max_count) -{ - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(semaphore == 0, PK_INVALID_SEMAPHORE_AT_CREATE); - PK_ERROR_IF((max_count != 0) && (initial_count > max_count), - PK_INVALID_ARGUMENT_SEMAPHORE); - } - - __pk_thread_queue_clear(&(semaphore->pending_threads)); - semaphore->count = initial_count; - semaphore->max_count = max_count; - - return PK_OK; -} - - - - - diff --git a/pk/kernel/pk_stack_init.c b/pk/kernel/pk_stack_init.c deleted file mode 100644 index c3ddc90a..00000000 --- a/pk/kernel/pk_stack_init.c +++ /dev/null @@ -1,85 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_stack_init.c -/// \brief PK stack initialization -/// -/// The entry points in this file are initialization routines - they are never -/// needed after PK initialization and their code space could be reclaimed by -/// the application after initialization if required. -/// -/// This code was split out from "pk_init.c" because it may be needed in a -/// thread configuration if threads are being created dynamically. in an -/// interrupt-only configuration it is not needed after \c pk_initialize(). - -#include "pk.h" - -/// Initialize a stack area. -/// -/// \param stack A pointer to the smallest legal address of the stack. The -/// stack address is modified as the stack is aligned and initialized. -/// -/// \param size A pointer to the size of the stack (in bytes). The size is -/// modified as the stack is aligned and initialized. At exit this is the -/// final usable stack area size aligned to the size of the PK_STACK_TYPE. -/// -/// PK makes no assumptions about size or alignment of the area provided as a -/// stack, and carefully aligns and initializes the stack. Regardless of how -/// the stack grows, the \a stack parameter is considered to be the lowest -/// legal address of the stack. - -int -__pk_stack_init(PkAddress *stack, - size_t *size) -{ - PkAddress mask; - size_t excess, i, count; - PK_STACK_TYPE *p; - - if (PK_STACK_DIRECTION < 0) { - - // Stacks grow down. The initial stack pointer is set to just above - // the last allocated stack address. This is legal for pre-decrement - // stacks, otherwise the initial address is first brought into range - // before alignment. The stack is aligned downward, then the size is - // adjusted to a multiple of the stack type. Stacks are optionally - // prepatterned. Alignment is assumed to be a power of 2. - - *stack += *size; - - if (!PK_STACK_PRE_DECREMENT) { - *stack -= sizeof(PK_STACK_TYPE); - *size -= sizeof(PK_STACK_TYPE); - } - - mask = PK_STACK_ALIGNMENT - 1; - excess = *stack & mask; - *stack -= excess; - *size -= excess; - *size = (*size / sizeof(PK_STACK_TYPE)) * sizeof(PK_STACK_TYPE); - - if (PK_STACK_CHECK) { - p = (PK_STACK_TYPE *)(*stack); - count = *size / sizeof(PK_STACK_TYPE); - for (i = 0; i < count; i++) { - if (PK_STACK_PRE_DECREMENT) { - *(--p) = PK_STACK_PATTERN; - } else { - *(p--) = PK_STACK_PATTERN; - } - } - } - - __pk_stack_create_initial_frame(stack, size); - - } else { - - PK_PANIC(PK_UNIMPLEMENTED); - } - - return PK_OK; -} - diff --git a/pk/kernel/pk_thread.h b/pk/kernel/pk_thread.h deleted file mode 100644 index acc32525..00000000 --- a/pk/kernel/pk_thread.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef __PK_THREAD_H__ -#define __PK_THREAD_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2015 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_thread.h -/// \brief Contains private declarations and definitions needed for threads -/// - -void -__pk_thread_map(PkThread* thread); - -void -__pk_thread_unmap(PkThread *thread); - - -// Interrupts must be disabled at entry. - -static inline int -__pk_thread_is_active(PkThread *thread) -{ - return ((thread->state != PK_THREAD_STATE_COMPLETED) && - (thread->state != PK_THREAD_STATE_DELETED)); -} - - -// Interrupts must be disabled at entry. - -static inline int -__pk_thread_is_mapped(PkThread *thread) -{ - return (thread->state == PK_THREAD_STATE_MAPPED); -} - - -// Interrupts must be disabled at entry. This is only called on mapped threads. - -static inline int -__pk_thread_is_runnable(PkThread *thread) -{ - return __pk_thread_queue_member(&__pk_run_queue, thread->priority); -} - - -// Interrupts must be disabled at entry. - -static inline PkThread* -__pk_thread_at_priority(PkThreadPriority priority) -{ - return (PkThread*)__pk_priority_map[priority]; -} - -#endif /* __PK_THREAD_H__ */ diff --git a/pk/kernel/pk_thread_core.c b/pk/kernel/pk_thread_core.c deleted file mode 100644 index 2966eb9b..00000000 --- a/pk/kernel/pk_thread_core.c +++ /dev/null @@ -1,573 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_thread_core.c -/// \brief PK thread APIs -/// -/// The entry points in this file are considered 'core' routines that will -/// always be present at runtime in any PK application that enables threads. - -#include "pk.h" -#include "pk_thread.h" - -#define __PK_THREAD_CORE_C__ - - -// This routine is only used locally. Interrupts must be disabled -// at entry. The caller must also have checked that the priority is free. -// This routine is only called on threads known to be in a suspended state, -// either PK_THREAD_STATE_SUSPENDED_RUNNABLE or -// PK_THREAD_STATE_SUSPENDED_BLOCKED. Mapping a runnable thread adds it to -// the run queue. Mapping a thread pending on a semaphore either takes the -// count and becomes runnable or adds the thread to the pending queue for the -// semaphore. Mapping a sleeping thread requires no further action -// here. Scheduling after the map must be handled by the caller. - -void -__pk_thread_map(PkThread* thread) -{ - PkThreadPriority priority; - - priority = thread->priority; - __pk_priority_map[priority] = thread; - - if (thread->state == PK_THREAD_STATE_SUSPENDED_RUNNABLE) { - - __pk_thread_queue_insert(&__pk_run_queue, priority); - - } else if (thread->flags & PK_THREAD_FLAG_SEMAPHORE_PEND) { - - if (thread->semaphore->count) { - - thread->semaphore->count--; - __pk_thread_queue_insert(&__pk_run_queue, priority); - - } else { - - __pk_thread_queue_insert(&(thread->semaphore->pending_threads), - priority); - } - } - - thread->state = PK_THREAD_STATE_MAPPED; - - if (PK_KERNEL_TRACE_ENABLE) { - if (__pk_thread_is_runnable(thread)) { - PK_KERN_TRACE("THREAD_MAPPED_RUNNABLE(%d)", priority); - } else if (thread->flags & PK_THREAD_FLAG_SEMAPHORE_PEND) { - PK_KERN_TRACE("THREAD_MAPPED_SEMAPHORE_PEND(%d)", priority); - } else { - PK_KERN_TRACE("THREAD_MAPPED_SLEEPING(%d)", priority); - } - } -} - - -// This routine is only used locally. Interrupts must be disabled -// at entry. This routine is only ever called on threads in the -// PK_THREAD_STATE_MAPPED. Unmapping a thread removes it from the priority -// map, the run queue and any semaphore pend, but does not cancel any -// timers. Scheduling must be handled by the code calling -// __pk_thread_unmap(). - -void -__pk_thread_unmap(PkThread *thread) -{ - PkThreadPriority priority; - - priority = thread->priority; - __pk_priority_map[priority] = 0; - - if (__pk_thread_is_runnable(thread)) { - - thread->state = PK_THREAD_STATE_SUSPENDED_RUNNABLE; - __pk_thread_queue_delete(&__pk_run_queue, priority); - - } else { - - thread->state = PK_THREAD_STATE_SUSPENDED_BLOCKED; - if (thread->flags & PK_THREAD_FLAG_SEMAPHORE_PEND) { - __pk_thread_queue_delete(&(thread->semaphore->pending_threads), - priority); - } - } -} - - -// Schedule and run the highest-priority mapped runnable thread. -// -// The priority of the next thread to run is first computed. This may be -// PK_THREADS, indicating that the only thread to run is the idle thread. -// This will always cause (or defer) a 'context switch' to the idle thread. -// Otherwise, if the new thread is not equal to the current thread this will -// also cause (or defer) a context switch. Note that scheduling is defined in -// terms of priorities but actually implemented in terms of PkThread pointers. -// -// If we are not yet in thread mode we're done - threads will be started by -// pk_start_threads() later. If we're in thread context a context switch -// happens immediately. In an interrupt context the switch is deferred to the -// end of interrupt processing. - -void -__pk_schedule(void) -{ - __pk_next_priority = __pk_thread_queue_min(&__pk_run_queue); - __pk_next_thread = __pk_priority_map[__pk_next_priority]; - - if ((__pk_next_thread == 0) || - (__pk_next_thread != __pk_current_thread)) { - - if (__pk_kernel_mode_thread()) { - if (__pk_kernel_context_thread()) { - if (__pk_current_thread != 0) { - __pk_switch(); - } else { - __pk_next_thread_resume(); - } - } else { - __pk_delayed_switch = 1; - } - } - } -} - - -// This routine is only used locally. -// -// Completion and deletion are pretty much the same thing. Completion is -// simply self-deletion of the current thread (which is mapped by -// definition.) The complete/delete APIs have slightly different error -// conditions but are otherwise the same. -// -// Deleting a mapped thread first unmaps (suspends) the thread, which takes -// care of removing the thread from any semaphores it may be pending on. Then -// any outstanding timer is also cancelled. -// -// If the current thread is being deleted we install the idle thread as -// __pk_current_thread, so scheduling is forced and no context is saved on -// the context switch. -// -// Note that we do not create trace events for unmapped threads since the trace -// tag only encodes the priority, which may be in use by a mapped thread. - -void -__pk_thread_delete(PkThread *thread, PkThreadState final_state) -{ - PkMachineContext ctx; - int mapped; - - pk_critical_section_enter(&ctx); - - mapped = __pk_thread_is_mapped(thread); - - if (mapped) { - __pk_thread_unmap(thread); - } - - __pk_timer_cancel(&(thread->timer)); - thread->state = final_state; - - if (mapped) { - - if (PK_KERNEL_TRACE_ENABLE) { - if (final_state == PK_THREAD_STATE_DELETED) { - PK_KERN_TRACE("THREAD_DELETED(%d)", thread->priority); - } else { - PK_KERN_TRACE("THREAD_COMPLETED(%d)", thread->priority); - } - } - - if (thread == __pk_current_thread) { - __pk_current_thread = 0; - } - __pk_schedule(); - } - - pk_critical_section_exit(&ctx); -} - - -// Generic thread timeout -// -// This routine is called as a timer callback either because a sleeping thread -// has timed out or a thread pending on a semaphore has timed out. If the -// thread is not already runnable then the the timeout flag is set, and if the -// thread is mapped it is scheduled. -// -// This implementation allows that a thread blocked on a timer may have been -// made runnable by some other mechanism, such as acquiring a semaphore. In -// order to provide an iteration-free implementation of -// pk_semaphore_release_all(), cancelling any semaphore timeouts is deferred -// until the thread runs again. -// -// Note that we do not create trace events for unmapped threads since the trace -// tag only encodes the priority, which may be in use by a mapped thread. - -void -__pk_thread_timeout(void *arg) -{ - PkMachineContext ctx; - PkThread *thread = (PkThread *)arg; - - pk_critical_section_enter(&ctx); - - switch (thread->state) { - - case PK_THREAD_STATE_MAPPED: - if (!__pk_thread_is_runnable(thread)) { - thread->flags |= PK_THREAD_FLAG_TIMED_OUT; - __pk_thread_queue_insert(&__pk_run_queue, thread->priority); - __pk_schedule(); - } - break; - - case PK_THREAD_STATE_SUSPENDED_RUNNABLE: - break; - - case PK_THREAD_STATE_SUSPENDED_BLOCKED: - thread->flags |= PK_THREAD_FLAG_TIMED_OUT; - thread->state = PK_THREAD_STATE_SUSPENDED_RUNNABLE; - break; - - default: - PK_PANIC(PK_THREAD_TIMEOUT_STATE); - } - - pk_critical_section_exit(&ctx); -} - - -// This routine serves as a container for the PK_START_THREADS_HOOK and -// actually starts threads. The helper routine __pk_call_pk_start_threads() -// arranges this routine to be called with interrupts disabled while running -// on the kernel stack. -// -// The reason for this roundabout is that we want to be able to run a hook -// routine (transparent to the application) that can hand over every last byte -// of free memory to "malloc()" - including the stack of main(). Since we -// always need to run on some stack, we chose to run the hook on the kernel -// stack. However to do this safely we need to make sure -// that no interrupts will happen during this time. When __pk_thread_resume() -// is finally called all stack-based context is lost but it doesn't matter at -// that point - it's a one-way street into thread execution. -// -// This is considered part of pk_start_threads() and so is also considered a -// 'core' routine. - -void -__pk_start_threads(void) -{ - PK_START_THREADS_HOOK; - - __pk_next_thread_resume(); - - PK_PANIC(PK_START_THREADS_RETURNED); -} - - -/// Start PK threads -/// -/// This routine starts the PK thread scheduler infrastructure. This routine -/// must be called after a call of \c pk_initialize(). This routine never -/// returns. Interrupt (+ timer) only configurations of PK need not call this -/// routine. -/// -/// Note: This tiny routine is considered a 'core' routine so that the -/// initialziation code can safely recover all 'init' code space before -/// starting threads. -/// -/// This routine typically does not return - any return value indicates an -/// error; see \ref pk_errors -/// -/// \retval -PK_ILLEGAL_CONTEXT_THREAD The API was called twice. - -int -pk_start_threads(void) -{ - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(__pk_kernel_mode_thread(), PK_ILLEGAL_CONTEXT_THREAD); - } - - __pk_call_pk_start_threads(); - - return 0; -} - - -/// Resume a suspended thread -/// -/// \param thread The thread to resume -/// -/// PK only allows one thread at a time to run at a given priority, and -/// implements the notion of a thread \e claiming a priority. A suspended -/// thread claims a priority when it is mapped by a call of -/// pk_thread_resume(). This API will succeed only if no other active thread -/// is currently mapped at the priority assigned to the thread. PK provides -/// the pk_thread_at_priority() API which allows an application-level -/// scheduler to correctly manage multiple threads running at the same -/// priority. -/// -/// If the thread was sleeping while suspended it remains asleep. However if -/// the sleep timer timed out while the thread was suspended it will be -/// resumed runnable. -/// -/// If the thread was blocked on a semaphore when it was suspended, then when -/// the thread is resumed it will attempt to reacquire the semaphore. -/// However, if the thread was blocked on a semaphore with timeout while -/// suspended and the timeout interval has passed, the thread will be resumed -/// runnable and see that the semaphore pend timed out. -/// -/// It is not an error to call pk_thread_resume() on a mapped -/// thread. However it is an error to call pk_thread_resume() on a completed -/// or deleted thread. -/// -/// Return values other than PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion, including calls on a \a thread that is -/// already mapped. -/// -/// \retval -PK_INVALID_THREAD_AT_RESUME1 The \a thread is a null (0) pointer. -/// -/// \retval -PK_INVALID_THREAD_AT_RESUME2 The \a thread is not active, -/// i.e. has completed or been deleted. -/// -/// \retval -PK_PRIORITY_IN_USE_AT_RESUME Another thread is already mapped at -/// the priority of the \a thread. - -int -pk_thread_resume(PkThread *thread) -{ - PkMachineContext ctx; - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(thread == 0, PK_INVALID_THREAD_AT_RESUME1); - } - - pk_critical_section_enter(&ctx); - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF_CRITICAL(!__pk_thread_is_active(thread), - PK_INVALID_THREAD_AT_RESUME2, - &ctx); - } - - if (!__pk_thread_is_mapped(thread)) { - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF_CRITICAL(__pk_priority_map[thread->priority] != 0, - PK_PRIORITY_IN_USE_AT_RESUME, - &ctx); - } - __pk_thread_map(thread); - __pk_schedule(); - } - - pk_critical_section_exit(&ctx); - - return PK_OK; -} - - -/// Suspend a thread -/// -/// Any active thread can be suspended. A suspended thread 1) remains active -/// but will not be scheduled; 2) relinquishes its priority assignment, -/// allowing another thread to be resumed at the suspended thread's priority; -/// and 3) disassociates from any semaphore mutual exclusion it may have been -/// participating in. -/// -/// If a sleeping thread is suspended, the sleep timer remains active but a -/// timeout of the timer simply marks the thread as runnable, but does not -/// resume the thread. -/// -/// If a thread blocked on a semaphore is suspended, the thread no longer -/// participates in the semaphore mutual exclusion. If the thread is later -/// resumed it will attempt to acquire the semaphore again the next time it -/// runs (unless it was blocked with a timeout and the timeout has expired). -/// -/// If a thread blocked on a semaphore with timeout is suspended, the -/// semaphore timeout timer continues to run. If the timer times out while the -/// thread is suspended the thread is simply marked runnable. If the thread is -/// later resumed, the suspended call of \c pk_semaphore_pend() will return the -/// timeout code -PK_SEMAPHORE_PEND_TIMED_OUT. -/// -/// Return values other than PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion, including calls on a \a thread that is -/// already suspended. -/// -/// \retval -PK_INVALID_THREAD_AT_SUSPEND1 The \a thread is a null (0) pointer -/// -/// \retval -PK_INVALID_THREAD_AT_SUSPEND2 The \a thread is not active, -/// i.e. has completed or been deleted. - -int -pk_thread_suspend(PkThread *thread) -{ - PkMachineContext ctx; - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF((thread == 0), PK_INVALID_THREAD_AT_SUSPEND1); - } - - pk_critical_section_enter(&ctx); - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF_CRITICAL(!__pk_thread_is_active(thread), - PK_INVALID_THREAD_AT_SUSPEND2, - &ctx); - } - - if (__pk_thread_is_mapped(thread)) { - - PK_KERN_TRACE("THREAD_SUSPENDED(%d)", thread->priority); - __pk_thread_unmap(thread); - __pk_schedule(); - } - - pk_critical_section_exit(&ctx); - - return PK_OK; -} - - -/// Delete a thread -/// -/// Any active thread can be deleted. If a thread is deleted it is removed -/// from the run queue, deleted from the timer queue (if sleeping or blocked -/// on a semaphore with timeout), and deleted from the semaphore mutual -/// exclusion if blocked on a semaphore. The thread control block is then -/// marked as deleted. -/// -/// Once a thread has completed or been deleted the thread structure and -/// thread stack areas can be used for other purposes. -/// -/// \param thread The thread to delete -/// -/// Return values other than PK_OK (0) are errors; see \ref pk_errors. If a -/// thread deletes itself this API does not return at all. -/// -/// \retval 0 Successful completion, including calls on a \a thread that has -/// completed or had already been deleted. -/// -/// -/// \retval -PK_INVALID_THREAD_AT_DELETE The \a thread is a null (0) pointer. - -int -pk_thread_delete(PkThread *thread) -{ - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(thread == 0, PK_INVALID_THREAD_AT_DELETE); - } - - __pk_thread_delete(thread, PK_THREAD_STATE_DELETED); - - return PK_OK; -} - - -/// Complete a thread -/// -/// If a thread ever returns from the subroutine defining the thread entry -/// point, the thread is removed from all PK kernel data structures and -/// marked completed. The thread routine can also use the API pk_complete() -/// to make this more explicit if desired. PK makes no distinction between -/// completed and deleted threads, but provides these indications for -/// the benefit of the application. -/// -/// Note that this API is only available from the current thread to mark its -/// own completion. -/// -/// Once a thread has completed or been deleted the thread structure and -/// thread stack areas can be used for other purposes. -/// -/// Any return value indicates an error; see \ref pk_errors. In the event of -/// a successful completion this API does not return to the caller, which is -/// always the thread context being completed. -/// -/// \retval -PK_ILLEGAL_CONTEXT_THREAD The API was not called from a thread -/// context. - -// Note: Casting __pk_current_thread removes the 'volatile' attribute. - -int -pk_complete(void) -{ - if (PK_ERROR_CHECK_API) { - PK_ERROR_UNLESS_THREAD_CONTEXT(); - } - - __pk_thread_delete((PkThread *)__pk_current_thread, - PK_THREAD_STATE_COMPLETED); - - return PK_OK; -} - -/// Sleep a thread for an interval relative to the current time. -/// -/// \param interval A time interval relative to the current timebase. -/// -/// Threads can use this API to sleep for a time relative to the current -/// timebase. The absolute timeout is \c pk_timebase_get() + \a interval. -/// -/// Sleeping threads are not scheduled, although they maintain their -/// priorities. This differs from thread suspension, where the suspended -/// thread relinquishes its priority. When the sleep timer times out the -/// thread becomes runnable again, and will run as soon as it becomes the -/// highest-priority mapped runnable thread. -/// -/// Sleeping threads may also be later suspended. In this case the Sleep timer -/// continues to run, and if it times out before the thread is resumed the -/// thread will be immediately runnable when it is resumed. -/// -/// See the PK specification for a full discussion of how PK handles -/// scheduling events at absolute times "in the past". Briefly stated, if the -/// \a interval is 0 or is so small that the absolute time becomes a "past" -/// time before the Sleep is actually scheduled, the thread will Sleep for the -/// briefest possible period supported by the hardware. -/// -/// Return values other than PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion. -/// -/// \retval -PK_ILLEGAL_CONTEXT_THREAD The API was not called from a thread -/// context. - -int -pk_sleep(PkInterval interval) -{ - PkTimebase time; - PkMachineContext ctx; - PkThread *current; - - if (PK_ERROR_CHECK_API) { - PK_ERROR_UNLESS_THREAD_CONTEXT(); - } - - time = pk_timebase_get() + PK_INTERVAL_SCALE(interval); - - pk_critical_section_enter(&ctx); - - current = (PkThread *)__pk_current_thread; - - current->timer.timeout = time; - __pk_timer_schedule(&(current->timer)); - - current->flags |= PK_THREAD_FLAG_TIMER_PEND; - - PK_KERN_TRACE("THREAD_SLEEP(%d)", current->priority); - - __pk_thread_queue_delete(&__pk_run_queue, current->priority); - __pk_schedule(); - - current->flags &= ~(PK_THREAD_FLAG_TIMER_PEND | PK_THREAD_FLAG_TIMED_OUT); - - pk_critical_section_exit(&ctx); - - return PK_OK; -} - -#undef __PK_THREAD_CORE_C__ diff --git a/pk/kernel/pk_thread_init.c b/pk/kernel/pk_thread_init.c deleted file mode 100644 index 97bce4c4..00000000 --- a/pk/kernel/pk_thread_init.c +++ /dev/null @@ -1,134 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_thread_init.c -/// \brief PK thread API initialization routines -/// -/// The entry points in this file are routines that are typically used during -/// initialization, and their code space could be deallocated and recovered if -/// no longer needed by the application after initialization. - -#include "pk.h" - -/// Create (initialize) a thread -/// -/// \param thread A pointer to an PkThread structure to initialize -/// -/// \param thread_routine The subroutine that implements the thread -/// -/// \param arg Private data to be passed as the argument to the thread -/// routine when it begins execution -/// -/// \param stack The stack space of the thread -/// -/// \param stack_size The size of the stack in bytes -/// -/// \param priority The initial priority of the thread -/// -/// The \a thread argument must be a pointer to an uninitialized or completed -/// or deleted thread. This \c PkThread structure \em is the thread, so this -/// memory area must not be modified by the application until the thread -/// completes or is deleted. PK can not tell if an PkThread structure is -/// currently in use as a thread control block.pk_thread_create() will -/// silently overwrite an PkThread structure that is currently in use. -/// -/// The stack area must be large enough to hold the dynamic stack requirements -/// of the entry point routine, and all subroutines and functions that might -/// be invoked on any path from the entry point. The stack must also always -/// be able to hold the thread context in the event the thread is preempted, -/// plus other critical context. PK aligns stack areas in machine-specific -/// ways, so that the actual stack area may reduced in size slightly if it is -/// not already aligned. -/// -/// Threads are created runnable but unmapped. A newly created thread will -/// not be eligible to run until a call of pk_thread_resume() targets the -/// thread. -/// -/// Return values other than PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_THREAD_AT_CREATE The \a thread is a null (0) pointer. -/// -/// \retval -PK_INVALID_ARGUMENT_THREAD1 the \a thread_routine is null (0) -/// -/// \retval -PK_INVALID_ARGUMENT_THREAD2 the \a priority is invalid, -/// -/// \retval -PK_INVALID_ARGUMENT_THREAD3 the stack area wraps around -/// the end of memory. -/// -/// \retval -PK_STACK_OVERFLOW The stack area at thread creation is smaller -/// than the minimum safe size. - -int -pk_thread_create(PkThread *thread, - PkThreadRoutine thread_routine, - void *arg, - PkAddress stack, - size_t stack_size, - PkThreadPriority priority) -{ - int rc; - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(thread == 0, PK_INVALID_THREAD_AT_CREATE); - PK_ERROR_IF((thread_routine == 0) || - (priority >= PK_THREADS), - PK_INVALID_ARGUMENT_THREAD1); - } - - rc = __pk_stack_init(&stack, &stack_size); - if (rc) { - return rc; - } - - thread->saved_stack_pointer = stack; - thread->stack_base = stack; - - if (PK_STACK_DIRECTION < 0) { - - thread->stack_limit = stack - stack_size; - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(thread->stack_limit > thread->stack_base, - PK_INVALID_ARGUMENT_THREAD2); - } - - } else { - - thread->stack_limit = stack + stack_size; - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(thread->stack_limit < thread->stack_base, - PK_INVALID_ARGUMENT_THREAD3); - } - } - - thread->semaphore = 0; - thread->priority = priority; - thread->state = PK_THREAD_STATE_SUSPENDED_RUNNABLE; - thread->flags = 0; - - pk_timer_create(&(thread->timer), - __pk_thread_timeout, - (void *)thread); - - __pk_thread_context_initialize(thread, thread_routine, arg); - - return rc; -} - - - - - - - - - - - - - - diff --git a/pk/kernel/pk_thread_util.c b/pk/kernel/pk_thread_util.c deleted file mode 100644 index bf2e21b7..00000000 --- a/pk/kernel/pk_thread_util.c +++ /dev/null @@ -1,291 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_thread_util.c -/// \brief PK thread utility APIs -/// -/// The entry points in this file are considered extra routines that will -/// only be included in a PK application that enables threads and uses at -/// least one of these interfaces. - -#include "pk.h" -#include "pk_thread.h" - -/// Get information about a thread. -/// -/// \param thread A pointer to the PkThread to query -/// -/// \param state The value returned through this pointer is the current state -/// of the thread; See \ref pk_thread_states. The caller can set this -/// parameter to the null pointer (0) if this information is not required. -/// -/// \param priority The value returned through this pointer is the current -/// priority of the thread. The caller can set this parameter to the null -/// pointer (0) if this information is not required. -/// -/// \param runnable The value returned through this pointer is 1 if the thread -/// is in state PK_THREAD_STATE_MAPPED and is currently in the run queue -/// (i.e., neither blocked on a semaphore nor sleeping), otherwise 0. The -/// caller can set this parameter to the null pointer (0) if this information -/// is not required. -/// -/// The information returned by this API can only be guaranteed consistent if -/// the API is called from a critical section. -/// -/// Return values other than PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_THREAD_AT_INFO The \a thread is a null (0) pointer. - -int -pk_thread_info_get(PkThread *thread, - PkThreadState *state, - PkThreadPriority *priority, - int *runnable) -{ - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(thread == 0, PK_INVALID_THREAD_AT_INFO); - } - - if (state) { - *state = thread->state; - } - if (priority) { - *priority = thread->priority; - } - if (runnable) { - *runnable = ((thread->state == PK_THREAD_STATE_MAPPED) && - __pk_thread_queue_member(&__pk_run_queue, - thread->priority)); - } - return PK_OK; -} - - -/// Change the priority of a thread. -/// -/// \param thread The thread whose priority will be changed -/// -/// \param new_priority The new priority of the thread -/// -/// \param old_priority The value returned through this pointer is the -/// old priority of the thread prior to the change. The caller can set -/// this parameter to the null pointer (0) if this information is not -/// required. -/// -/// Thread priorities can be changed by the \c pk_thread_priority_change() -/// API. This call will fail if the thread pointer is invalid or if the thread -/// is mapped and the new priority is currently in use. The call will succeed -/// even if the \a thread is suspended, completed or deleted. The -/// application-level scheduling algorithm is completely responsible for the -/// correctness of the application in the event of suspended, completed or -/// deleted threads. -/// -/// Return values other than PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion, including the redundant case of -/// attempting to change the priority of the thread to its current priority. -/// -/// \retval -PK_INVALID_THREAD_AT_CHANGE The \a thread is null (0) or -/// otherwise invalid. -/// -/// \retval -PK_INVALID_ARGUMENT_THREAD_CHANGE The \a new_priority is invalid. -/// -/// \retval -PK_PRIORITY_IN_USE_AT_CHANGE The \a thread is mapped and the \a -/// new_priority is currently in use by another thread. - -int -pk_thread_priority_change(PkThread *thread, - PkThreadPriority new_priority, - PkThreadPriority *old_priority) -{ - PkMachineContext ctx; - PkThreadPriority priority; - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(thread == 0, PK_INVALID_THREAD_AT_CHANGE); - PK_ERROR_IF(new_priority > PK_THREADS, - PK_INVALID_ARGUMENT_THREAD_CHANGE); - } - - pk_critical_section_enter(&ctx); - - priority = thread->priority; - - if (priority != new_priority) { - - if (!__pk_thread_is_mapped(thread)) { - - thread->priority = new_priority; - - } else { - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF_CRITICAL(__pk_priority_map[new_priority] != 0, - PK_PRIORITY_IN_USE_AT_CHANGE, - &ctx); - } - - __pk_thread_unmap(thread); - thread->priority = new_priority; - __pk_thread_map(thread); - __pk_schedule(); - } - } - - if (old_priority) { - *old_priority = priority; - } - - pk_critical_section_exit(&ctx); - - return PK_OK; -} - - -/// Return a pointer to the thread (if any) mapped at a given priority. -/// -/// \param priority The thread priority of interest -/// -/// \param thread The value returned through this pointer is a pointer to the -/// thread currently mapped at the given priority level. If no thread is -/// mapped, or if the \a priority is the priority of the idle thread, the -/// pointer returned will be null (0). -/// -/// The information returned by this API can only be guaranteed consistent if -/// the API is called from a critical section. -/// -/// Return values other than PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion. -/// -/// \retval -PK_INVALID_ARGUMENT_THREAD_PRIORITY The \a priority is invalid -/// or the \a thread parameter is null (0). - -int -pk_thread_at_priority(PkThreadPriority priority, - PkThread **thread) -{ - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF((priority > PK_THREADS) || (thread == 0), - PK_INVALID_ARGUMENT_THREAD_PRIORITY); - } - - *thread = __pk_thread_at_priority(priority); - - return PK_OK; -} - - -/// Swap thread priorities -/// -/// \param thread_a A pointer to an initialized PkThread -/// -/// \param thread_b A pointer to an initialized PkThread -/// -/// This API swaps the priorities of \a thread_a and \a thread_b. The API is -/// provided to support general and efficient application-directed scheduling -/// algorithms. The requirements on the \a thread_a and \a thread_b arguments -/// are that they are valid pointers to initialized PkThread structures, that -/// the current thread priorities of both threads are legal, and that if a -/// thread is currently mapped, that the new thread priority is not otherwise -/// in use. -/// -/// The API does not require either thread to be mapped, or even to be active. -/// It is legal for one or both of the swap partners to be suspended, deleted -/// or completed threads. The application is completely responsible for the -/// correctness of scheduling algorithms that might operate on inactive or -/// suspended threads. -/// -/// The API does not change the mapped status of a thread. A thread will be -/// mapped after the call of pk_thread_priority_swap() if and only if it was -/// mapped prior to the call. If the new priority of a mapped thread is -/// currently in use (by a thread other than the swap partner), then the -/// PK_PRIORITY_IN_USE_AT_SWAP error is signalled and the swap does not take -/// place. This could only happen if the swap partner is not currently mapped. -/// -/// It is legal for a thread to swap its own priority with another thread. The -/// degenerate case that \a thread_a and \a thread_b are equal is also legal - -/// but has no effect. -/// -/// Return values other than PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion, including the redundant cases that do not -/// actually change priorities, or the cases that assign new priorities to -/// suspended, completed or deleted threads. -/// -/// \retval -PK_INVALID_THREAD_AT_SWAP1 One or both of \a thread_a and -/// \a thread_b is null (0) or otherwise invalid, -/// -/// \retval -PK_INVALID_THREAD_AT_SWAP2 the priorities of One or both of -/// \a thread_a and \a thread_b are invalid. -/// -/// \retval -PK_INVALID_ARGUMENT One or both of the priorities -/// of \a thread_a and \a thread_b is invalid. -/// -/// \retval -PK_PRIORITY_IN_USE_AT_SWAP Returned if a thread is mapped and the -/// new thread priority is currently in use by another thread (other than the -/// swap partner). - -int -pk_thread_priority_swap(PkThread* thread_a, PkThread* thread_b) -{ - PkMachineContext ctx; - PkThreadPriority priority_a, priority_b; - int mapped_a, mapped_b; - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF((thread_a == 0) || (thread_b == 0), - PK_INVALID_THREAD_AT_SWAP1); - } - - pk_critical_section_enter(&ctx); - - if (thread_a != thread_b) { - - mapped_a = __pk_thread_is_mapped(thread_a); - mapped_b = __pk_thread_is_mapped(thread_b); - priority_a = thread_a->priority; - priority_b = thread_b->priority; - - if (PK_ERROR_CHECK_API) { - int priority_in_use; - PK_ERROR_IF_CRITICAL((priority_a > PK_THREADS) || - (priority_b > PK_THREADS), - PK_INVALID_THREAD_AT_SWAP2, - &ctx); - priority_in_use = - (mapped_a && !mapped_b && - (__pk_thread_at_priority(priority_b) != 0)) || - (!mapped_a && mapped_b && - (__pk_thread_at_priority(priority_a) != 0)); - PK_ERROR_IF_CRITICAL(priority_in_use, - PK_PRIORITY_IN_USE_AT_SWAP, &ctx); - } - - if (mapped_a) { - __pk_thread_unmap(thread_a); - } - if (mapped_b) { - __pk_thread_unmap(thread_b); - } - thread_a->priority = priority_b; - thread_b->priority = priority_a; - if (mapped_a) { - __pk_thread_map(thread_a); - } - if (mapped_b) { - __pk_thread_map(thread_b); - } - __pk_schedule(); - } - - pk_critical_section_exit(&ctx); - - return PK_OK; -} - diff --git a/pk/kernel/pk_timer_core.c b/pk/kernel/pk_timer_core.c deleted file mode 100644 index 59b9d628..00000000 --- a/pk/kernel/pk_timer_core.c +++ /dev/null @@ -1,401 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_timer_core.c -/// \brief PK portable kernel timer handler -/// -/// This file contains core routines that would be needed by any application -/// that requires PK timer support at runtime. -/// -/// PK implements a 'tickless' kernel - all events are scheduled at absolute -/// times of the PK timebase. This approach gives the application full -/// control over granularity of event scheduling. Scheduling in absolute time -/// opens up the possibility of scheduling events "in the past". PK -/// uniformly handles this case by scheduling "past" events to occur 1 -/// timebase tick in the future, so that timer callbacks are always run in the -/// expected interrupt context. -/// -/// PK implements the time queue as a simple unordered list of events, plus a -/// dedicated variable that holds the earliest timeout of any event in the -/// list. This is thought to be an appropriate data structure for the -/// following reasons: -/// -/// - PK applications will be small and will not schedule a large number of -/// events. Therefore the cost of scanning the list each time an event times -/// out is balanced against the cost of maintaining the list as a sorted data -/// structure each time an event is added or removed from the event queue. -/// -/// - PK applications may schedule and cancel many, many more events (safety -/// timeouts) than are ever allowed to expire. Events can be added and deleted -/// from the simple DEQUE very quickly since there is no sorting -/// overhead. -/// -/// Events are added to the queue simply by placing them at the end of the -/// queue. If the new event times out earlier than the previous earliest -/// event, the hardware timeout is rescheduled for the new event time. Events -/// are deleted from the queue (cancelled) simply by deleting them. Deletion -/// does not affect the hardware timeout, even if the deleted event would have -/// been the next to time out. It is not an error for the timer handler to -/// take a timer interrupt and find no events pending. Pending events can -/// also be rescheduled in place. -/// -/// When a timeout occurs the event list is scanned from the beginning, and -/// any event that has timed out has its callback processed. -/// Since event and callback processing take -/// time, the list is potentially scanned multiple times until there are no -/// more timed-out events in the list. -/// -/// Note that callbacks are not necessarily processed in time-order. In this -/// sense the PK time queue is like a traditional tick-based time queue in -/// that events are effectively lumped into groups of events that time out -/// together. In a tick-based kernel the 'lump' is the tick interval; here -/// the 'lump' is a variable interval that corresponds to the time it takes to -/// process the entire event list. -/// -/// Timer callbacks are typically run with interrupt preemption enabled. -/// Special callbacks may run without preemption. This is the only part of -/// the PK kernel where data structures of indeterminate size are processed. -/// During processing of the event list by the timer interrupt handler, the -/// consideration of each event always includes a window of preemptability. - -#define __PK_TIMER_CORE_C__ - -#include "pk.h" - -// Declare the timer bottom half handler -static PK_BH_HANDLER(__pk_timer_bh_handler); - -// Define the timer bottom half handler that the interrupt handler will -// schedule -PK_BH_STATIC_CREATE(pk_timer_bh, __pk_timer_bh_handler, 0); - - -// This routine is only used in this file, and will always be called in a -// critical section. - -static inline int -timer_active(PkTimer* timer) -{ - return pk_deque_is_queued((PkDeque*)timer); -} - - -// This is the kernel version of pk_timer_cancel(). -// -// This routine is used here and by thread and semaphore routines. -// External interrupts must be disabled at entry. -// -// If the timer is active, then there is a special case if we are going to -// delete the 'cursor' - that is the timer that __pk_timer_handler() is going -// to handle next. In this case we need to move the cursor to the next timer -// in the queue. -// -// Note that cancelling a timer does not cause a re-evaluation of the next -// timeout. This will happen naturally when the current timeout expires. - -int -__pk_timer_cancel(PkTimer *timer) -{ - int rc; - PkDeque* timer_deque = (PkDeque*)timer; - PkTimeQueue* tq = &__pk_time_queue; - - if (!timer_active(timer)) { - - rc = -PK_TIMER_NOT_ACTIVE; - - } else { - - if (timer_deque == tq->cursor) { - tq->cursor = tq->cursor->next; - } - pk_deque_delete(timer_deque); - rc = 0; - } - return rc; -} - - -// This is the kernel version of pk_timer_schedule(). -// -// This routine is used here and by thread and semaphore routines. -// interrupts must be disabled at entry. -// -// Unless the timer is already active it is enqueued in the doubly-linked -// timer list by inserting the timer at the end of the queue. Then the -// hardware timeout is scheduled if necessary. If the time queue 'cursor' != 0 -// we are in the midst of processing the time queue, and the end of time queue -// processing will schedule the next hardware timemout. - -void -__pk_timer_schedule(PkTimer* timer) -{ - PkTimeQueue* tq = &__pk_time_queue; - - if (!timer_active(timer)) { - pk_deque_push_back((PkDeque*)tq, (PkDeque*)timer); - } - - if (timer->timeout < tq->next_timeout) { - tq->next_timeout = timer->timeout; - if (tq->cursor == 0) { - __pk_schedule_hardware_timeout(tq->next_timeout); - } - } -} - - -// The tickless timer mechanism has timed out. Note that due to timer -// deletions and other factors, there may not actually be a timer in the queue -// that has timed out - but it doesn't matter (other than for efficiency). -// -// This routine must not be entered reentrantly. -// -// First, time out any timers that have expired. Timers in the queue are -// unordered, so we have to check every one. Since passing through the -// loop takes time, we may have to make multiple passes until we know -// that there are no timers in the queue that have already timed -// out. Note that it would also work to only go through the loop once and -// let the hardware scheduler take care of looping, but that would imply -// more overhead than the current implementation. -// -// On each pass through the loop tq->next_timeout computes the minimum timeout -// of events remaining in the queue. This is the only part of the kernel that -// searches a list of indefinite length. Kernel interrupt latency is mitigated -// by running this function as a bottom half. As such, interrupts are only -// disabled when explicitly requested. -// -// Because interrupt preemption is enabled during processing, and preempting -// handlers may invoke time queue operations, we need to establish a pointer -// to the next entry to be examined (tq->cursor) before enabling interupts. -// It's possible that this pointer will be changed by other interrupt handlers -// that cancel the timer pointed to by tq->cursor. -// -// The main loop iterates on the PkDeque form of the time queue, casting each -// element back up to the PkTimer as it is processed. - -static void -__pk_timer_bh_handler(void* arg) -{ - PkMachineContext ctx; - PkTimeQueue* tq; - PkTimebase now; - PkTimer* timer; - PkDeque* timer_deque; - PkTimerCallback callback; - - tq = &__pk_time_queue; - - // Check if we entered the function while it was running in another context. - if (PK_ERROR_CHECK_KERNEL) { - if (tq->cursor != 0) { - PK_PANIC(PK_TIMER_HANDLER_INVARIANT); - } - } - - pk_critical_section_enter(&ctx); - - while ((now = pk_timebase_get()) >= tq->next_timeout) { - tq->next_timeout = PK_TIMEBASE_MAX; - timer_deque = ((PkDeque*)tq)->next; - - // Iterate through the entire timer list, calling the callback of - // timed-out elements and finding the timer that will timeout next, - // which is stored in tq->next_timeout. - while (timer_deque != (PkDeque*)tq) { - - timer = (PkTimer*)timer_deque; - - // Setting this to a non-zero value indicates we are in the middle - // of processing the time queue. - tq->cursor = timer_deque->next; - - if (timer->timeout <= now) { - - // The timer timed out. It is removed from the queue. - // - // The callback may be made with interrupt preemption enabled - // or disabled. However to mitigate kernel interrupt latency - // we go ahead and open up to interrupts after the callback if - // the callback itself was not preemptible. - - pk_deque_delete(timer_deque); - - pk_critical_section_exit(&ctx); - - callback = timer->callback; - if (callback) { - callback(timer->arg); - } - - } else { - - // This timer has not timed out. Its timeout will simply - // participate in the computation of the next timeout. - tq->next_timeout = MIN(timer->timeout, tq->next_timeout); - pk_critical_section_exit(&ctx); - } - - timer_deque = tq->cursor; - pk_critical_section_enter(&ctx); - } - - // Time has passed since we checked the time. Loop back - // to check the time again and see if enough time has passed - // that the next timer has timed out too. - } - - pk_critical_section_exit(&ctx); - - // This marks that we are no longer processing the time queue - tq->cursor = 0; - - // Finally, reschedule the next timeout - __pk_schedule_hardware_timeout(tq->next_timeout); -} - - -void -__pk_timer_handler(void) -{ - //schedule the timer bottom half handler which - //is preemptible. - pk_bh_schedule(&pk_timer_bh); -} - - -/// Schedule a timer for an interval relative to the current time. -/// -/// \param timer The PkTimer to schedule. -/// -/// \param interval The timer will be scheduled to time out at the current -/// time (pk_timebase_get()) plus this \a interval. -/// -/// Once created with pk_timer_create() a timer can be \e scheduled, which -/// queues the timer in the kernel time queue. It is not an error to call \c -/// pk_timer_schedule() on a timer that is already scheduled in the time -/// queue - the timer is simply rescheduled with the new characteristics. -/// -/// Return values other than PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_TIMER_AT_SCHEDULE A a null (0) pointer was provided as -/// the \a timer argument. -/// - -int -pk_timer_schedule(PkTimer *timer, - PkInterval interval) -{ - PkMachineContext ctx; - PkTimebase timeout = pk_timebase_get() + PK_INTERVAL_SCALE(interval); - - pk_critical_section_enter(&ctx); - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(timer == 0, PK_INVALID_TIMER_AT_SCHEDULE); - } - - timer->timeout = timeout; - __pk_timer_schedule(timer); - - pk_critical_section_exit(&ctx); - - return PK_OK; -} - - -/// Cancel (dequeue) a timer. -/// -/// \param timer The PkTimer to cancel. -/// -/// Timers can be canceled at any time. It is never an error to call -/// pk_timer_cancel() on an PkTimer object after it is created. Memory used -/// by an PkTimer can be safely reused for another purpose after a successful -/// call ofpk_timer_cancel(). -/// -/// Return values other than PK_OK (0) are not necessarily errors; see \ref -/// pk_errors -/// -/// The following return codes are non-error codes: -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_TIMER_NOT_ACTIVE The \a timer is not currently scheduled, -/// i.e. it was never scheduled or has timed out. This code is returned for -/// information only and is not considered an error. -/// -/// The following return codes are error codes: -/// -/// \retval -PK_INVALID_TIMER_AT_CANCEL The \a timer is a null (0) pointer. -/// - -int -pk_timer_cancel(PkTimer *timer) -{ - PkMachineContext ctx; - int rc = PK_OK; - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(timer == 0, PK_INVALID_TIMER_AT_CANCEL); - } - - pk_critical_section_enter(&ctx); - - rc = __pk_timer_cancel(timer); - - pk_critical_section_exit(&ctx); - - return rc; -} - - -/// Get information about a timer. -/// -/// \param timer The PkTimer to query -/// -/// \param timeout The API returns the absolute timeout of the timer through -/// this pointer. If the timer is active, this is the current timeout. If -/// the timer has timed out then this is the previous absolute timeout. If -/// the timer was never scheduled this will be 0. The caller can set this -/// parameter to the null pointer (0) if this information is not required. -/// -/// \param active If the value returned through this pointer is 1 then the -/// timer is active (currently scheduled), otherwise the value will be 0 -/// indicating an inactive timer. The caller can set this parameter to the -/// null pointer (0) if this information is not required. -/// -/// The information returned by this API can only be guaranteed consistent if -/// the API is called from a critical section. -/// -/// Return values other than PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_TIMER_AT_INFO The \a timer is a null (0) pointer. - -int -pk_timer_info_get(PkTimer *timer, - PkTimebase *timeout, - int *active) - -{ - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(timer == 0, PK_INVALID_TIMER_AT_INFO); - } - - if (timeout) { - *timeout = timer->timeout; - } - if (active) { - *active = timer_active(timer); - } - - return PK_OK; -} - -#undef __PK_TIMER_CORE_C__ diff --git a/pk/kernel/pk_timer_init.c b/pk/kernel/pk_timer_init.c deleted file mode 100644 index 457f78c4..00000000 --- a/pk/kernel/pk_timer_init.c +++ /dev/null @@ -1,62 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_timer_init.c -/// \brief PK timer initialization -/// -/// The entry points in this file might only be used during initialization of -/// the application. In this case the code space for these routines could be -/// recovered and reused after initialization. - -#include "pk.h" - - -/// Create (initialize) a timer. -/// -/// \param timer The PkTimer to initialize. -/// -/// \param callback The timer callback -/// -/// \param arg Private data provided to the callback. -/// -/// Once created with pk_timer_create() a timer can be scheduled with -/// pk_timer_schedule() or pk_timer_schedule_absolute(), which queues the -/// timer in the kernel time queue. Timers can be cancelled by a call of -/// pk_timer_cancel(). -/// -/// Timers created with pk_timer_create() are always run as -/// bottom-half handlers with interrupt preemption enabled. Timer callbacks are -/// free to enter critical sections if required, but must -/// always exit with interrupts enabled. -/// -/// Caution: PK has no way to know if an PkTimer structure provided to -/// pk_timer_create() is safe to use as a timer, and will silently modify -/// whatever memory is provided. -/// -/// Return values other then PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_TIMER_AT_CREATE The \a timer is a null (0) pointer. - -int -pk_timer_create(PkTimer *timer, - PkTimerCallback callback, - void *arg) -{ - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF((timer == 0), PK_INVALID_TIMER_AT_CREATE); - } - - pk_deque_element_create((PkDeque*)timer); - timer->timeout = 0; - timer->callback = callback; - timer->arg = arg; - - return PK_OK; -} - - diff --git a/pk/kernel/pkkernelfiles.mk b/pk/kernel/pkkernelfiles.mk deleted file mode 100644 index df7872bd..00000000 --- a/pk/kernel/pkkernelfiles.mk +++ /dev/null @@ -1,32 +0,0 @@ -# @file pkkernelfiles.mk -# -# @brief mk for including architecture independent pk object files -# -# @page ChangeLogs Change Logs -# @section pkkernelfiles.mk -# @verbatim -# -# -# Change Log ****************************************************************** -# Flag Defect/Feature User Date Description -# ------ -------------- ---------- ------------ ----------- -# -# @endverbatim -# -########################################################################## -# Include -########################################################################## - - -########################################################################## -# Object Files -########################################################################## -PK-C-SOURCES = pk_core.c pk_init.c pk_stack_init.c pk_bh_core.c pk_debug_ptrs.c - -PK-TIMER-C-SOURCES += pk_timer_core.c pk_timer_init.c - -PK-THREAD-C-SOURCES += pk_thread_init.c pk_thread_core.c pk_thread_util.c \ - pk_semaphore_init.c pk_semaphore_core.c - -PK_OBJECTS += $(PK-C-SOURCES:.c=.o) - diff --git a/pk/ppe/Makefile b/pk/ppe/Makefile deleted file mode 100644 index 833dbfdf..00000000 --- a/pk/ppe/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -# This Makefile compiles all of the PK code required for the PPE port -# of PK. See the "pk.mk" file in this directory. - -#all generated files from this makefile will end up in obj/$(IMAGE_NAME)/pk -export SUB_OBJDIR = /pk - -include img_defs.mk -include pkppefiles.mk - -ifeq "$(PK_TIMER_SUPPORT)" "1" -PPE_OBJECTS += ${PPE-TIMER-C-SOURCES:.c=.o} ${PPE-TIMER-S-SOURCES:.S=.o} -endif - -ifeq "$(PK_THREAD_SUPPORT)" "1" -PPE_OBJECTS += ${PPE-THREAD-C-SOURCES:.c=.o} ${PPE-THREAD-S-SOURCES:.S=.o} -endif - -ifeq "$(PPE_ASYNC_SUPPORT)" "1" -PPE_OBJECTS += ${PPE-ASYNC-C-SOURCES:.c=.o} ${PPE-ASYNC-S-SOURCES:.S=.o} -endif - -OBJS := $(addprefix $(OBJDIR)/, $(PPE_OBJECTS)) - -libpk.a: kernel ppe42 trace ppe - $(AR) crs $(OBJDIR)/libpk.a $(OBJDIR)/*.o - -.PHONY: clean ppe kernel ppe42 trace -ppe: $(OBJS) - -trace: - $(MAKE) -I $(IMAGE_SRCDIR) -C ../trace - -kernel: - $(MAKE) -I $(IMAGE_SRCDIR) -C ../kernel - -ppe42: - $(MAKE) -I $(IMAGE_SRCDIR) -C ../ppe42 - - -$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) - -$(OBJDIR): - mkdir -p $(OBJDIR) - -clean: - rm -fr $(OBJDIR) - -ifneq ($(MAKECMDGOALS),clean) -include $(OBJS:.o=.d) -endif diff --git a/pk/ppe/pk_port.h b/pk/ppe/pk_port.h deleted file mode 100644 index b88078f2..00000000 --- a/pk/ppe/pk_port.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __PK_PORT_H__ -#define __PK_PORT_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_port.h -/// \brief The top-level CME environment header for PK. - -#define HWMACRO_PPE - -#include "ppe42.h" -#include "ppe_timebase.h" - -#endif /* __PK_PORT_H__ */ diff --git a/pk/ppe/pkppefiles.mk b/pk/ppe/pkppefiles.mk deleted file mode 100644 index 79b7baae..00000000 --- a/pk/ppe/pkppefiles.mk +++ /dev/null @@ -1,33 +0,0 @@ -# @file pkppefiles.mk -# -# @brief mk for including ppe object files -# -# @page ChangeLogs Change Logs -# @section pkppefiles.mk -# @verbatim -# -# -# Change Log ****************************************************************** -# Flag Defect/Feature User Date Description -# ------ -------------- ---------- ------------ ----------- -# -# @endverbatim -# -########################################################################## -# Object Files -########################################################################## - -PPE-C-SOURCES = ppe_init.c -PPE-S-SOURCES = - -PPE-TIMER-C-SOURCES = -PPE-TIMER-S-SOURCES = - -PPE-THREAD-C-SOURCES = -PPE-THREAD-S-SOURCES = - -PPE-ASYNC-C-SOURCES = -PPE-ASYNC-S-SOURCES = - -PPE_OBJECTS += $(PPE-C-SOURCES:.c=.o) $(PPE-S-SOURCES:.S=.o) - diff --git a/pk/ppe/ppe.h b/pk/ppe/ppe.h deleted file mode 100644 index 05df6a61..00000000 --- a/pk/ppe/ppe.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef __PPE_H__ -#define __PPE_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pgp.h -/// \brief The PPE environment for PK. - -// This is a 'circular' reference in PK, but included here to simplify PGAS -// programming. - -#ifndef HWMACRO_PPE -#define HWMACRO_PPE -#include "ppe42.h" -#endif - -#include "ppe_common.h" - -#endif /* __PPE_H__ */ diff --git a/pk/ppe/ppe_common.h b/pk/ppe/ppe_common.h deleted file mode 100644 index c7df60bd..00000000 --- a/pk/ppe/ppe_common.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef __PPE_COMMON_H__ -#define __PPE_COMMON_H__ - -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe_common.h -/// \brief Common header for PPE -/// -/// This header is maintained as part of the PK port for PPE, but needs to be -/// physically present in the PMX area to allow dropping PMX code as a whole -/// to other teams. - -// -*- WARNING: This file is maintained as part of PK. Do not edit in -*- -// -*- the PMX area as your edits will be lost. -*- - -#ifndef __ASSEMBLER__ -#include -#endif - -/// This constant is used to define the size of the table of interrupt handler -/// structures as well as a limit for error checking. -/// NOTE: This can be specific to each PPE type (SBE, PPE, GPE) -#define EXTERNAL_IRQS 64 - -#ifdef __ASSEMBLER__ -/// This macro contains PPE specific code. -/// Since standalone models of the PPE do not support external interrupts -/// we just set the code to 64 (phantom interrupt) - .macro hwmacro_get_ext_irq - - li %r4, 64 - - .endm - -/// Redirect the .hwmacro_irq_cfg_bitmaps macro to call our ppe specific implementation -/// This is called from the ppe42_exceptions.S file. -/// NOTE: The standalone version of PPE doesn't support external interrupts so this -/// does nothing. - .macro .hwmacro_irq_cfg_bitmaps - .endm - - -#endif /* __ASSEMBLER__ */ - -#endif /* __PPE_COMMON_H__ */ diff --git a/pk/ppe/ppe_init.c b/pk/ppe/ppe_init.c deleted file mode 100644 index 09feea67..00000000 --- a/pk/ppe/ppe_init.c +++ /dev/null @@ -1,25 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe_init.c -/// \brief PK initialization for PPE -/// -/// The entry points in this routine are used during initialization. This -/// code space can be deallocated and reassigned after application -/// initialization if required. - -#include "pk.h" - -/// PPE environment initial setup. -/// -/// This is setup common to all PPE HW Macro applications. This setup takes place -/// during boot, before main() is called. - -void -__hwmacro_setup(void) -{ - //async_initialize(); -} diff --git a/pk/ppe/ppe_timebase.h b/pk/ppe/ppe_timebase.h deleted file mode 100644 index 45da0080..00000000 --- a/pk/ppe/ppe_timebase.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef __PPE_TIMEBASE_H__ -#define __PPE_TIMEBASE_H__ - -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2015 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file ppe_timebase.h -/// \brief support for using the OCB 32 bit timebase register -/// - -#include "pk.h" - -//The timebase register will never be supported in the base ppe model -#ifdef APPCFG_USE_EXT_TIMEBASE -#error "External timebase is not supported on the PPE standalone model" -#endif /* APPCFG_USE_EXT_TIMEBASE */ - -#ifndef __ASSEMBLER__ - -//assembly function is defined in ppe42_timebase.S -uint32_t pk_timebase32_get(void); - -#endif /* __ASSEMBLER__ */ - -#endif /* __PPE_TIMEBASE_H__ */ diff --git a/pk/ppe42/.empty b/pk/ppe42/.empty deleted file mode 100644 index e69de29b..00000000 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 -#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 _lzi - 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 _sti - 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 _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 - 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__ - - -### **************************************************************************** -### _lzi -### _sti -### **************************************************************************** - - .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 - - -### **************************************************************************** -### _lzsd -### _stsd -### **************************************************************************** - - .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 -### _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 -### .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 - -/// 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 and mf 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\\ where \ 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 diff --git a/pk/std/Makefile b/pk/std/Makefile deleted file mode 100644 index 4101935d..00000000 --- a/pk/std/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -# This Makefile compiles all of the PK code required for the STD (standard PPE) port -# of PK. See the "pk.mk" file in this directory. - -#all generated files from this makefile will end up in obj/$(IMAGE_NAME)/pk -export SUB_OBJDIR = /pk - -include img_defs.mk -include pkstdfiles.mk - -ifeq "$(PK_TIMER_SUPPORT)" "1" -STD_OBJECTS += ${STD-TIMER-C-SOURCES:.c=.o} ${STD-TIMER-S-SOURCES:.S=.o} -endif - -ifeq "$(PK_THREAD_SUPPORT)" "1" -STD_OBJECTS += ${STD-THREAD-C-SOURCES:.c=.o} ${STD-THREAD-S-SOURCES:.S=.o} -endif - -ifeq "$(STD_ASYNC_SUPPORT)" "1" -STD_OBJECTS += ${STD-ASYNC-C-SOURCES:.c=.o} ${STD-ASYNC-S-SOURCES:.S=.o} -endif - -OBJS := $(addprefix $(OBJDIR)/, $(STD_OBJECTS)) - -libpk.a: kernel ppe42 trace std - $(AR) crs $(OBJDIR)/libpk.a $(OBJDIR)/*.o - -.PHONY: clean std kernel ppe42 trace -std: $(OBJS) - -trace: - $(MAKE) -I $(IMAGE_SRCDIR) -C ../trace - -kernel: - $(MAKE) -I $(IMAGE_SRCDIR) -C ../kernel - -ppe42: - $(MAKE) -I $(IMAGE_SRCDIR) -C ../ppe42 - - -$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) - -$(OBJDIR): - mkdir -p $(OBJDIR) - -clean: - rm -fr $(OBJDIR) - -ifneq ($(MAKECMDGOALS),clean) -include $(OBJS:.o=.d) -endif diff --git a/pk/std/pk_port.h b/pk/std/pk_port.h deleted file mode 100644 index 4d400cc5..00000000 --- a/pk/std/pk_port.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef __PK_PORT_H__ -#define __PK_PORT_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_port.h -/// \brief The top-level standard PPE environment header for PK. - -#define HWMACRO_STD - -#include "ppe42.h" -#include "std_timebase.h" - -#endif /* __PK_PORT_H__ */ diff --git a/pk/std/pkstdfiles.mk b/pk/std/pkstdfiles.mk deleted file mode 100644 index 7133bd47..00000000 --- a/pk/std/pkstdfiles.mk +++ /dev/null @@ -1,33 +0,0 @@ -# @file pkstdfiles.mk -# -# @brief mk for including std object files -# -# @page ChangeLogs Change Logs -# @section pkstdfiles.mk -# @verbatim -# -# -# Change Log ****************************************************************** -# Flag Defect/Feature User Date Description -# ------ -------------- ---------- ------------ ----------- -# -# @endverbatim -# -########################################################################## -# Object Files -########################################################################## - -STD-C-SOURCES = std_init.c std_irq_init.c -STD-S-SOURCES = - -STD-TIMER-C-SOURCES = -STD-TIMER-S-SOURCES = - -STD-THREAD-C-SOURCES = -STD-THREAD-S-SOURCES = - -STD-ASYNC-C-SOURCES = -STD-ASYNC-S-SOURCES = - -STD_OBJECTS += $(STD-C-SOURCES:.c=.o) $(STD-S-SOURCES:.S=.o) - diff --git a/pk/std/std.h b/pk/std/std.h deleted file mode 100644 index c4e9dda6..00000000 --- a/pk/std/std.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __STD_H__ -#define __STD_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pgp.h -/// \brief The STD environment for PK. - -#ifndef HWMACRO_STD -#define HWMACRO_STD -#include "ppe42.h" -#endif - -#include "std_register_addresses.h" -#include "std_common.h" - -#endif /* __STD_H__ */ diff --git a/pk/std/std_common.h b/pk/std/std_common.h deleted file mode 100644 index 38bc1621..00000000 --- a/pk/std/std_common.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef __STD_COMMON_H__ -#define __STD_COMMON_H__ - -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file cme_common.h -/// \brief Common header for standard PPE's -/// - -#ifndef __ASSEMBLER__ -#include -#endif - -//#include "cmehw_interrupts.h" -#include "pk.h" -#include "std_irq_config.h" - -#ifdef __ASSEMBLER__ -/// This macro contains standard PPE code for determining what IRQ caused the -/// external exception handler to be invoked by the PPE - -/// Check for interrupts pending in the interrupt status register while the IRQ -/// is computed. The IRQ is expected to be stored in r4. If no IRQ is -/// pending then load the phantom irq # (EXTERNAL_IRQS). -/// -/// r1, r2, r3, and r13 must not be modified. All other registers may be used. -/// - .macro hwmacro_get_ext_irq - - _lvdg d5, STD_LCL_EISTR #load the 64bit interrupt status into d5 - cntlzw r4, r5 - cmpwible r4, 31, call_external_irq_handler #branch if irq is lt or eq to 31 - - ## No IRQ pending in r5. Try r6. - ## Note: irq # will be 64 (phantom irq) if no bits were set in either register - - cntlzw r4, r6 - addi r4, r4, 32 - - .endm - -/// Redirect the .hwmacro_irq_cfg_bitmaps macro to call our standard PPE implementation -/// This is called from the ppe42_exceptions.S file. - .macro .hwmacro_irq_cfg_bitmaps - .std_irq_cfg_bitmaps - .endm - -#endif /* __ASSEMBLER__ */ - -#endif /* __STD_COMMON_H__ */ diff --git a/pk/std/std_init.c b/pk/std/std_init.c deleted file mode 100644 index b0aae325..00000000 --- a/pk/std/std_init.c +++ /dev/null @@ -1,50 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file std_init.c -/// \brief PK initialization for a standard PPE. -/// -/// The entry points in this routine are used during initialization. This -/// code space can be deallocated and reassigned after application -/// initialization if required. - -#include "pk.h" - -/// Standard PPE environment initial setup. -/// -/// This is setup common to all standard PPE Macro applications. This setup takes place -/// during boot, before main() is called. - -void -__hwmacro_setup(void) -{ - //mask all interrupts - out64(STD_LCL_EIMR_OR, 0xffffffffffffffffull); - - //Set all interrupts to active low, level sensitive by default - out64(STD_LCL_EIPR_CLR, 0xffffffffffffffffull); - out64(STD_LCL_EITR_CLR, 0xffffffffffffffffull); - - //set up the configured type - out64(STD_LCL_EITR_OR, g_ext_irqs_type); - - //set up the configured polarity - out64(STD_LCL_EIPR_OR, g_ext_irqs_polarity); - - //clear the status of all active-high interrupts (has no affect on - //level sensitive interrupts) - out64(STD_LCL_EISR_CLR, g_ext_irqs_polarity); - - //clear the status of all active-low interrupts (has no affect on - //level sensitive interrupts) - out64(STD_LCL_EISR_OR, ~g_ext_irqs_polarity); - - //unmask the interrupts that are to be enabled by default - out64(STD_LCL_EIMR_CLR, g_ext_irqs_enable); - - //wait for the last operation to complete - sync(); -} diff --git a/pk/std/std_irq.h b/pk/std/std_irq.h deleted file mode 100644 index 3920997e..00000000 --- a/pk/std/std_irq.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef __STD_IRQ_H__ -#define __STD_IRQ_H__ - -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file occhw_irq.h -/// \brief Standard PPE Externnal Interrupt handling for PK -/// -/// The standard PPE interrupt controller supports a maximum of 64 interrupts with -/// simple OR combining of the interrupt signals. -/// -/// The standard PPE interrupt controller allows interrupt status to be set directly by -/// software. It contains a 'mask' register, unlike most 405 interrupt -/// controllers that have an 'enable' register. The standard PPE mask and status -/// registers also have atomic CLR/OR function so that it is never necessary -/// to enter a critical section to enable/disable/clear interrupts and -/// interrupt status. - -#include "std_common.h" -#include "std_register_addresses.h" -#include "ppe42.h" - -#ifndef __ASSEMBLER__ - -/// Enable an interrupt by clearing the mask bit. - -UNLESS__PPE42_IRQ_CORE_C__(extern) -inline void -pk_irq_enable(PkIrqId irq) -{ - out64(STD_LCL_EIMR_CLR, STD_IRQ_MASK64(irq)); -} - - -/// Disable an interrupt by setting the mask bit. - -UNLESS__PPE42_IRQ_CORE_C__(extern) -inline void -pk_irq_disable(PkIrqId irq) -{ - out64(STD_LCL_EIMR_OR, STD_IRQ_MASK64(irq)); -} - - -/// Clear interrupt status with an CLR mask. Only meaningful for -/// edge-triggered interrupts. - -UNLESS__PPE42_IRQ_CORE_C__(extern) -inline void -pk_irq_status_clear(PkIrqId irq) -{ - out64(STD_LCL_EISR_CLR, STD_IRQ_MASK64(irq)); -} - - -/// Get IRQ status as a 0 or non-0 integer - -UNLESS__PPE42_IRQ_CORE_C__(extern) -inline int -pk_irq_status_get(PkIrqId irq) -{ - return (in64(STD_LCL_EISR) & STD_IRQ_MASK64(irq)) != 0; -} - - -/// Set or clear interrupt status explicitly. - -UNLESS__PPE42_IRQ_CORE_C__(extern) -inline void -pk_irq_status_set(PkIrqId irq, int value) -{ - if (value) { - out64(STD_LCL_EISR_OR, STD_IRQ_MASK64(irq)); - } else { - out64(STD_LCL_EISR_CLR, STD_IRQ_MASK64(irq)); - } -} - - -#endif /* __ASSEMBLER__ */ - -#endif /* __STD_IRQ_H__ */ diff --git a/pk/std/std_irq_config.h b/pk/std/std_irq_config.h deleted file mode 100644 index 1c0326f1..00000000 --- a/pk/std/std_irq_config.h +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef __STD_IRQ_CONFIG_H__ -#define __STD_IRQ_CONFIG_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2015 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file std_irq_config.h -/// \brief Contains data and macros pertaining to external interrupt -/// configuration for a standard PPE. -/// - -#include "pk_app_cfg.h" - -/// This constant is used to define the size of the table of interrupt handler -/// structures as well as a limit for error checking. -#define EXTERNAL_IRQS 64 - -// Standard interrupt type values (level or edge) -#define STD_IRQ_TYPE_LEVEL 0 -#define STD_IRQ_TYPE_EDGE 1 - -// Standard interrupt polarity values (high or low, rising falling) -#define STD_IRQ_POLARITY_LO 0 -#define STD_IRQ_POLARITY_FALLING 0 -#define STD_IRQ_POLARITY_HI 1 -#define STD_IRQ_POLARITY_RISING 1 - -// Standard interrupt mask values (masked or enabled) -#define STD_IRQ_MASKED 0 -#define STD_IRQ_ENABLED 1 - -// Fail to compile if the application does not define this -#ifndef APPCFG_EXT_IRQS_CONFIG -#error "APPCFG_EXT_IRQS_CONFIG must be defined in pk_app_cfg.h" -#endif - -// Fail to compile if the application does not define this -#ifndef APPCFG_IRQ_INVALID_MASK -#error "APPCFG_IRQ_INVALID_MASK must be defined in pk_app_cfg.h" -#endif - -#ifndef __ASSEMBLER__ - -/// This expression recognizes only those IRQ numbers that have named -/// (non-reserved) interrupts in the standard PPE interrupt controller. -#define STD_IRQ_VALID(irq) \ - ({unsigned __irq = (unsigned)(irq); \ - ((__irq < EXTERNAL_IRQS) && \ - ((STD_IRQ_MASK64(__irq) & \ - APPCFG_IRQ_INVALID_MASK) == 0));}) - -/// This is a 64-bit mask, with big-endian bit 'irq' set. -#define STD_IRQ_MASK64(irq) (0x8000000000000000ull >> (irq)) - -#else - -//Untyped assembler version of STD_IRQ_MASK64 -#define STD_IRQ_MASK64(irq) (0x8000000000000000 >> (irq)) - -#endif /* __ASSEMBLER__ */ - -#ifndef __ASSEMBLER__ -/// These globals are statically initialized elsewhere -extern uint64_t g_ext_irqs_type; -extern uint64_t g_ext_irqs_valid; -extern uint64_t g_ext_irqs_polarity; -extern uint64_t g_ext_irqs_enable; -#endif - -#ifdef __ASSEMBLER__ -/// These macros aid in the initialization of the external interrupt globals. I would -/// prefer to use CPP macros, but they don't support recursive macros which I use to -/// convert the variable number of interrupts that a processor can control into static -/// bitmaps used by __hwmacro_setup() at runtime. - - - //helper macro for setting up the irq configuration bitmaps for a standard PPE - .macro .std_irq_config irq_num=-1 irq_type=-1 irq_polarity=-1 irq_mask=-1 parms:vararg - .if (( \irq_num == -1 ) && ( \irq_type == -1 ) && ( \irq_polarity == -1 ) && ( \irq_mask == -1 )) -#.if ( .ext_irqs_defd != .ext_irqs_valid ) -#.error "###### .std_irq_config: Missing configuration for one or more interrupts ######" -#.endif - - .section .sdata - .align 3 - .global g_ext_irqs_type - .global g_ext_irqs_polarity - .global g_ext_irqs_enable - g_ext_irqs_polarity: - .quad .ext_irqs_polarity - g_ext_irqs_type: - .quad .ext_irqs_type - g_ext_irqs_enable: - .quad .ext_irqs_enable - .else - .if (( \irq_num < 0 ) || ( \irq_num > (EXTERNAL_IRQS - 1))) - .error "###### .std_irq_config: invalid irq number \irq_num ######" - .elseif ((.ext_irqs_valid & (1 << ( EXTERNAL_IRQS - 1 - \irq_num ))) == 0 ) - .error "###### .std_irq_config: Attempt to configure invalid irq number \irq_num ######" - .elseif (.ext_irqs_defd & (1 << ( EXTERNAL_IRQS - 1 - \irq_num ))) - .error "###### .std_irq_config: duplicate definition for irq \irq_num ######" - .else - .ext_irqs_defd = .ext_irqs_defd | (1 << ( EXTERNAL_IRQS - 1 - \irq_num )) - .endif - - .if (( \irq_type < 0 ) || ( \irq_type > 1 )) - .error "###### .std_irq_config: invalid/unspecified irq type \irq_type for irq \irq_num ######" - .else - .ext_irqs_type = .ext_irqs_type | ( \irq_type << ( EXTERNAL_IRQS - 1 - \irq_num )) - .endif - - .if (( \irq_polarity < 0 ) || ( \irq_polarity > 1 )) - .error "###### .std_irq_config: invalid/unspecified irq polarity ( \irq_polarity ) for irq \irq_num ######" - .else - .ext_irqs_polarity = .ext_irqs_polarity | ( \irq_polarity << ( EXTERNAL_IRQS - 1 - \irq_num )) - .endif - - .if (( \irq_mask < 0 ) || ( \irq_mask > 1 )) - .error "###### .std_irq_config: invalid/unspecified irq mask ( \irq_mask ) for irq \irq_num ######" - .else - .ext_irqs_enable = .ext_irqs_enable | ( \irq_mask << ( EXTERNAL_IRQS - 1 - \irq_num )) - .endif - - .std_irq_config \parms - .endif - .endm - - //Top level macro for generating interrupt configuration globals for a standard PPE - .macro .std_irq_cfg_bitmaps - .ext_irqs_valid = ~(APPCFG_IRQ_INVALID_MASK) - .ext_irqs_type = 0 - .ext_irqs_polarity = 0 - .ext_irqs_enable = 0 - .irq_mask = 0 - .ext_irqs_defd = 0 - .std_irq_config APPCFG_EXT_IRQS_CONFIG - .endm - -#endif /*__ASSEMBLER__*/ - -#endif /*__STD_IRQ_CONFIG_H__*/ diff --git a/pk/std/std_irq_init.c b/pk/std/std_irq_init.c deleted file mode 100644 index 80ae0f19..00000000 --- a/pk/std/std_irq_init.c +++ /dev/null @@ -1,105 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2015 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file std_irq_init.c -/// \brief Standard PPE IRQ initialization code for PK -/// -/// The entry points in this file are initialization routines that could be -/// eliminated/deallocated by the application to free up storage if they are -/// no longer needed after initialization. - -#include "pk.h" - -/// Define the polarity and trigger condition for an interrupt. -/// -/// It is up to the application to take care of any side effects that may -/// occur from programming or reprogramming the interrupt controller. For -/// example, changing edge/level sensitivity or active level may set or clear -/// interrupt status in the controller. -/// -/// Note that PK allows this API to be called from any context, and changes -/// to the interrupt controller are made from a critical section. -/// -/// Return values other then PK_OK (0) are errors; see \ref pk_errors -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_ARGUMENT_IRQ_SETUP One or more arguments are invalid, -/// including an invalid \a irq, or invalid \a polarity or \a trigger parameters. - -int -pk_irq_setup(PkIrqId irq, - int polarity, - int trigger) -{ - PkMachineContext ctx; - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(!STD_IRQ_VALID(irq) || - !((polarity == PK_IRQ_POLARITY_ACTIVE_HIGH) || - (polarity == PK_IRQ_POLARITY_ACTIVE_LOW)) || - !((trigger == PK_IRQ_TRIGGER_LEVEL_SENSITIVE) || - (trigger == PK_IRQ_TRIGGER_EDGE_SENSITIVE)), - PK_INVALID_ARGUMENT_IRQ_SETUP); - } - - pk_critical_section_enter(&ctx); - - if (polarity == PK_IRQ_POLARITY_ACTIVE_HIGH) { - out64(STD_LCL_EIPR_OR, STD_IRQ_MASK64(irq)); - } else { - out64(STD_LCL_EIPR_CLR, STD_IRQ_MASK64(irq)); - } - - if (trigger == PK_IRQ_TRIGGER_EDGE_SENSITIVE) { - out64(STD_LCL_EITR_OR, STD_IRQ_MASK64(irq)); - } else { - out64(STD_LCL_EITR_CLR, STD_IRQ_MASK64(irq)); - } - - pk_critical_section_exit(&ctx); - - return PK_OK; -} - - -/// (Re)define the IRQ handler and priority for an interrupt. -/// Return values other then PK_OK (0) are errors; see \ref pk_errors -/// -/// Note that PK allows this API to be called from any context, and changes -/// to the interrupt controller are made from a critical section. -/// -/// \retval 0 Successful completion -/// -/// \retval -PK_INVALID_ARGUMENT_IRQ_HANDLER One or more arguments are -/// invalid, including an invalid \a irq, a null (0) \a handler, -/// or invalid \a priority. - -int -pk_irq_handler_set(PkIrqId irq, - PkIrqHandler handler, - void *arg) -{ - PkMachineContext ctx; - - if (PK_ERROR_CHECK_API) { - PK_ERROR_IF(!STD_IRQ_VALID(irq) || - (handler == 0), - PK_INVALID_ARGUMENT_IRQ_HANDLER); - } - - pk_critical_section_enter(&ctx); - - __ppe42_irq_handlers[irq].handler = handler; - __ppe42_irq_handlers[irq].arg = arg; - - pk_critical_section_exit(&ctx); - - return PK_OK; -} - - - diff --git a/pk/std/std_register_addresses.h b/pk/std/std_register_addresses.h deleted file mode 100644 index 18153c7e..00000000 --- a/pk/std/std_register_addresses.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef __STD_REGISTER_ADDRESSES_H__ -#define __STD_REGISTER_ADDRESSES_H__ - -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2015 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file std_register_addresses.h -/// \brief Symbolic addresses for a standard PPE - -#include "pk.h" - -// Define the base address for the external interrupt controller registers -// This can be overridden in the pk_app_cfg.h file -#ifndef STD_EIC_BASE -#define STD_EIC_BASE 0xC0000000 -#endif - -// Define the base address for the PPE mode registers -// This can be overridden in the pk_app_cfg.h file -#ifndef STD_PMR_BASE -#define STD_PMR_BASE 0xC0000100 -#endif - -// Note: This list only contains registers that are needed by PK. If -// an application requires other registers, it should define them -// elsewhere (i.e., cme_register_addresses.h) -#define STD_LCL_EISR (STD_EIC_BASE + 0x0000) -#define STD_LCL_EISR_OR (STD_EIC_BASE + 0x0010) -#define STD_LCL_EISR_CLR (STD_EIC_BASE + 0x0018) -#define STD_LCL_EIMR (STD_EIC_BASE + 0x0020) -#define STD_LCL_EIMR_OR (STD_EIC_BASE + 0x0030) -#define STD_LCL_EIMR_CLR (STD_EIC_BASE + 0x0038) -#define STD_LCL_EIPR (STD_EIC_BASE + 0x0040) -#define STD_LCL_EIPR_OR (STD_EIC_BASE + 0x0050) -#define STD_LCL_EIPR_CLR (STD_EIC_BASE + 0x0058) -#define STD_LCL_EITR (STD_EIC_BASE + 0x0060) -#define STD_LCL_EITR_OR (STD_EIC_BASE + 0x0070) -#define STD_LCL_EITR_CLR (STD_EIC_BASE + 0x0078) -#define STD_LCL_EISTR (STD_EIC_BASE + 0x0080) -#define STD_LCL_EINR (STD_EIC_BASE + 0x00a0) - -#define STD_LCL_TSEL (STD_PMR_BASE + 0x0000) -#define STD_LCL_TBR (STD_PMR_BASE + 0x0040) - -#endif // __STD_REGISTER_ADDRESSES_H__ - diff --git a/pk/std/std_timebase.h b/pk/std/std_timebase.h deleted file mode 100644 index 855320d5..00000000 --- a/pk/std/std_timebase.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef __STD_TIMEBASE_H__ -#define __STD_TIMEBASE_H__ - -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2015 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file std_timebase.h -/// \brief support for using the standard PPE 32 bit timebase register -/// -/// Each standard PPE has it's own timebase register that runs at a constant -/// frequency. - -#include "pk.h" - -#ifndef __ASSEMBLER__ - -#ifndef APPCFG_USE_EXT_TIMEBASE -static inline -uint32_t pk_timebase32_get(void) -{ - return (uint32_t)((in64(STD_LCL_TBR)) >> 32); -} - -#else -//assembly function is defined in ppe42_timebase.S -uint32_t pk_timebase32_get(void); - -#endif /* APPCFG_USE_EXT_TIMEBASE */ - -#else - - .macro _pk_timebase32_get rT, rA - lis \rA, STD_LCL_TBR@ha - lvd \rT, STD_LCL_TBR@l(\rA) - .endm - -#endif /* __ASSEMBLER__ */ - -#endif /* __STD_TIMEBASE_H__ */ diff --git a/pk/trace/Makefile b/pk/trace/Makefile deleted file mode 100644 index 69e95ebd..00000000 --- a/pk/trace/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 pktracefiles.mk - -ifeq "$(PK_TIMER_SUPPORT)" "1" -PKTRACE_OBJECTS += ${PKTRACE-TIMER-C-SOURCES:.c=.o} ${PKTRACE-TIMER-S-SOURCES:.S=.o} -endif - -ifeq "$(PK_THREAD_SUPPORT)" "1" -PKTRACE_OBJECTS += ${PKTRACE-THREAD-C-SOURCES:.c=.o} ${PKTRACE-THREAD-S-SOURCES:.S=.o} -endif - -OBJS := $(addprefix $(OBJDIR)/, $(PKTRACE_OBJECTS)) - -all: $(OBJS) - -$(OBJS) $(OBJS:.o=.d): | $(OBJDIR) - -$(OBJDIR): - mkdir -p $(OBJDIR) - -ifneq ($(MAKECMDGOALS),clean) -include $(OBJS:.o=.d) -endif diff --git a/pk/trace/pk_trace.h b/pk/trace/pk_trace.h deleted file mode 100644 index b19a5193..00000000 --- a/pk/trace/pk_trace.h +++ /dev/null @@ -1,279 +0,0 @@ -#ifndef __PK_TRACE_H__ -#define __PK_TRACE_H__ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_trace.h -/// \brief Macros and declarations for the PK Firmware Tracing Facility. -/// - -#include - -#define PK_TRACE_VERSION 2 - -#ifndef PK_TRACE_SZ -#define PK_TRACE_SZ 1024 -#endif - -//Fail compilation if size is not a power of 2 -#if ((PK_TRACE_SZ - 1) & PK_TRACE_SZ) -#error "PK_TRACE_SZ is not a power of two!!!" -#endif - -//Fail compilation if size is smaller than 64 bytes -#if (PK_TRACE_SZ < 64) -#error "PK_TRACE_SZ must be at least 64 bytes!!!" -#endif - -//Mask for calculating offsets into the trace circular buffer -#define PK_TRACE_CB_MASK (PK_TRACE_SZ - 1) - -#define STRINGIFY_HELPER(x) #x -#define STRINGIFY(x) STRINGIFY_HELPER(x) - -#define PPE_IMG_STRING STRINGIFY(IMAGE_NAME) - -#ifdef PK_TRACE_HASH_PREFIX -#if (PK_TRACE_HASH_PREFIX > 0xffff) -#error PK_TRACE_HASH_PREFIX must be defined as a 16 bit constant value -#endif -#endif //PK_TRACE_HASH_PREFIX - -//This provides a 128ns tick (assuming a 32ns clock period) -//and 4 different format values -#define PK_TRACE_TS_BITS 30 - -#define PK_TRACE_FORMAT_BITS (32 - PK_TRACE_TS_BITS) - -#define PK_TRACE_TS_MASK (0xfffffffful << PK_TRACE_FORMAT_BITS) -#define PK_TRACE_FORMAT_MASK (~PK_TRACE_TS_MASK) - -#define PK_GET_TRACE_FORMAT(w32) (PK_TRACE_FORMAT_MASK & w32) -#define PK_GET_TRACE_TIME(w32) (PK_TRACE_TS_MASK & w32) - -//Set the trace timer period to be the maximum -//32 bit time minus 2 seconds (assuming a 32ns tick) -//This allows for up to 1 second of interrupt latency + -//1 second for PK_TRACE_MTBT while only requiring a trace -//every 135 seconds in order to maintain the 64bit timebase. -#define PK_TRACE_TIMER_PERIOD (0xfffffffful - 62500000) - -//The Maximum Time Between Traces. In order to reduce the time that interrupts -//are disabled for tracing, reading of the time stamp is not done atomically -//with alocating an entry in the circular buffer. This means that the -//timestamps might not appear in order in the trace buffer. This is a -//problem because our calculation of the 64 bit timebase uses the unsigned -//difference of the current 32bit timestamp and the previous one and if they -//are out of order it will result in a very large difference. To solve this -//problem, any time that the parser code sees a very large difference (larger -//than PK_TRACE_MTBT) it will treat it as a negative number. -#define PK_TRACE_MTBT (0xfffffffful - 31250000) - -#define PK_TRACE_MAX_PARMS 4 - -//This is the maximum number of bytes allowed to be traced in a binary trace -//entry. -//The trace version needs to change if this changes. -#define PK_TRACE_MAX_BINARY 256 - -//clip the largest binary trace according to the trace buffer size. -//(The trace version does not need to change if this changes as long -// as it remains less than PK_TRACE_MAX_BINARY) -#if (PK_TRACE_SZ <= 256) -#define PK_TRACE_CLIPPED_BINARY_SZ PK_TRACE_SZ / 2 -#else -#define PK_TRACE_CLIPPED_BINARY_SZ PK_TRACE_MAX_BINARY -#endif - -//Trace formats that are supported -typedef enum -{ - PK_TRACE_FORMAT_EMPTY, - PK_TRACE_FORMAT_TINY, - PK_TRACE_FORMAT_BIG, - PK_TRACE_FORMAT_BINARY, -}PkTraceFormat; //pk_trace_format_t; - -//This combines the timestamp and the format bits into a -//single 32 bit word. -typedef union -{ - struct - { - uint32_t timestamp : PK_TRACE_TS_BITS; - uint32_t format : PK_TRACE_FORMAT_BITS; - }; - uint32_t word32; -}PkTraceTime; //pk_trace_time_t; - -//PK trace uses a 16 bit string format hash value -typedef uint16_t PkTraceHash; //pk_trace_hash_t; - -//The constant 16 bit hash value is combined with a -//16 bit parameter value when doing a tiny trace -typedef union -{ - struct - { - PkTraceHash string_id; - uint16_t parm; - }; - uint32_t word32; -}PkTraceTinyParms; //pk_trace_tiny_parms_t; - -//A tiny trace fits within a single 8 byte word. This includes -//the timestamp, format bits, hash id, and a 16 bit parameter. -typedef union -{ - struct - { - PkTraceTinyParms parms; - PkTraceTime time_format; - }; - uint64_t word64; -}PkTraceTiny; //pk_trace_tiny_t; - -//Larger traces that require a 32 bit parameter or more than one -//parameter use the big trace format. The number of parms and -//the 'complete' flag are combined with the hash id. 'complete' -//is set to 0 initially and set to one only after all of the trace -//data has been written. -typedef union -{ - struct - { - PkTraceHash string_id; - uint8_t complete; - uint8_t num_parms; - }; - uint32_t word32; -}PkTraceBigParms; //pk_trace_big_parms_t; - -typedef union -{ - struct - { - PkTraceBigParms parms; - PkTraceTime time_format; - }; - uint64_t word64; -}PkTraceBig; //pk_trace_big_t; - -//Binary traces are handled in a similar fashion to big traces, except -//that instead of having a number of parameters, we have number of bytes. -typedef union -{ - struct - { - PkTraceHash string_id; - uint8_t complete; - uint8_t num_bytes; - }; - uint32_t word32; -}PkTraceBinaryParms; //pk_trace_binary_parms_t; - -typedef union -{ - struct - { - PkTraceBinaryParms parms; - PkTraceTime time_format; - }; - uint64_t word64; -}PkTraceBinary; //pk_trace_binary_t; - -//This is a generic structure that can be used to retrieve data -//for tiny, big, and binary formatted entries. -typedef union -{ - struct - { - PkTraceHash string_id; - union - { - uint16_t parm16; - struct - { - uint8_t complete; - uint8_t bytes_or_parms_count; - }; - }; - PkTraceTime time_format; - }; - uint64_t word64; -}PkTraceGeneric; //pk_trace_generic_t; - -//This is a format that might be used in the future for tracing -//a 64 bit timestamp so that we don't fill up the buffer with periodic -//timer traces. It is not currently used. -#if 0 -typedef union -{ - struct - { - uint32_t upper32; - PkTraceTime time_format; - }; - uint64_t word64; -}PkTraceTime64; //pk_trace_time64_t; -#endif - -//It would probably be more accurate to call this a footer since it -//actually resides at the highest address of each trace entry. These eight -//bytes contain information that allow us to walk the trace buffer from the -//most recent entry to the oldest entry. -typedef union -{ - PkTraceGeneric generic; - PkTraceBinary binary; - PkTraceBig big; - PkTraceTiny small; -}PkTraceEntryFooter; //pk_trace_entry_header_t; - - -//This is the data that is updated (in the buffer header) every time we add -//a new entry to the buffer. -typedef union -{ - struct - { - uint32_t tbu32; - uint32_t offset; - }; - uint64_t word64; -}PkTraceState; //pk_trace_state_t; - -#define PK_TRACE_IMG_STR_SZ 16 - -//Header data for the trace buffer that is used for parsing the data. -//Note: pk_trace_state_t contains a uint64_t which is required to be -//placed on an 8-byte boundary according to the EABI Spec. This also -//causes cb to start on an 8-byte boundary. -typedef struct -{ - //these values are needed by the parser - uint16_t version; - uint16_t rsvd; - char image_str[PK_TRACE_IMG_STR_SZ]; - uint16_t instance_id; - uint16_t partial_trace_hash; - uint16_t hash_prefix; - uint16_t size; - uint32_t max_time_change; - uint32_t hz; - uint32_t pad; - uint64_t time_adj64; - - //updated with each new trace entry - PkTraceState state; - - //circular trace buffer - uint8_t cb[PK_TRACE_SZ]; -}PkTraceBuffer; //pk_trace_buffer_t; - -extern PkTraceBuffer g_pk_trace_buf; - -#endif /* __PK_TRACE_H__ */ diff --git a/pk/trace/pk_trace_big.c b/pk/trace/pk_trace_big.c deleted file mode 100644 index 4ba212da..00000000 --- a/pk/trace/pk_trace_big.c +++ /dev/null @@ -1,92 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_trace_big.c -/// \brief PK Trace function that supports up to four 32-bit parameters -/// -/// The pk_trace_big function is only called (via some macro magic) if the -/// caller passes in a single parameter (not including the format string) -/// that is larger than 16 bits to the PK_TRACE(...) macro. -/// - -#include "pk.h" -#include "pk_trace.h" - -#if (PK_TRACE_SUPPORT && PK_TIMER_SUPPORT) -void pk_trace_big(uint32_t i_hash_and_count, - uint64_t i_parm1, uint64_t i_parm2) -{ - PkTraceBig footer; - PkTraceBig* footer_ptr; - PkTraceState state; - uint64_t* ptr64; - uint64_t tb64; - PkMachineContext ctx; - uint32_t parm_size; - uint32_t cur_offset; - uint32_t footer_offset; - - //fill in the footer data - tb64 = pk_timebase_get(); - footer.parms.word32 = i_hash_and_count; //this has the parm count and hash - state.tbu32 = tb64 >> 32; - footer.time_format.word32 = tb64 & 0x00000000ffffffffull; - footer.time_format.format = PK_TRACE_FORMAT_BIG; - - //round up to 8 byte boundary - if(footer.parms.num_parms <= 2) - { - parm_size = 8; - } - else - { - parm_size = 16; - } - - //*****The following operations must be done atomically***** - pk_critical_section_enter(&ctx); - - //load in the offset in the cb for the entry we are adding - cur_offset = g_pk_trace_buf.state.offset; - - //Find the offset for the footer (at the end of the entry) - footer_offset = cur_offset + parm_size; - - //calculate the address of the footer - ptr64 = (uint64_t*)&g_pk_trace_buf.cb[footer_offset & PK_TRACE_CB_MASK]; - - //calculate the offset for the next entry in the cb - state.offset = footer_offset + sizeof(PkTraceBig); - - //update the cb state (tbu and offset) - g_pk_trace_buf.state.word64 = state.word64; - - //write the data to the circular buffer including the - //timesamp, string hash, and 16bit parameter - *ptr64 = footer.word64; - - //*******************exit the critical section*************** - pk_critical_section_exit(&ctx); - - - //write parm values to the circular buffer - footer_ptr = (PkTraceBig*)ptr64; - ptr64 = (uint64_t*)&g_pk_trace_buf.cb[cur_offset & PK_TRACE_CB_MASK]; - *ptr64 = i_parm1; - if(parm_size > 8) - { - ptr64 = (uint64_t*)&g_pk_trace_buf.cb[(cur_offset + 8) & PK_TRACE_CB_MASK]; - *ptr64 = i_parm2; - } - - //Mark the trace entry update as being completed - footer_ptr->parms.complete = 1; - -} - -#endif - - diff --git a/pk/trace/pk_trace_binary.c b/pk/trace/pk_trace_binary.c deleted file mode 100644 index 58b417a3..00000000 --- a/pk/trace/pk_trace_binary.c +++ /dev/null @@ -1,91 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_trace_binary.c -/// \brief PK Trace function for dumping memory contents -/// -/// The pk_trace_binary function is called by the PK_TRACE_BINARY() macro. -/// - - -#include "pk.h" -#include "pk_trace.h" - -#if (PK_TRACE_SUPPORT && PK_TIMER_SUPPORT) -void pk_trace_binary(uint32_t i_hash_and_size, void* bufp) -{ - PkTraceBinary footer; - PkTraceBinary* footer_ptr; - PkTraceState state; - uint64_t* ptr64; - uint64_t tb64; - PkMachineContext ctx; - uint32_t data_size; - uint32_t cb_offset; - uint32_t footer_offset; - uint8_t* dest; - uint8_t* src; - uint32_t index; - - //fill in the footer data - tb64 = pk_timebase_get(); - footer.parms.word32 = i_hash_and_size; //this has the size and hash - state.tbu32 = tb64 >> 32; - footer.time_format.word32 = tb64 & 0x00000000ffffffffull; - footer.time_format.format = PK_TRACE_FORMAT_BINARY; - - //round up to 8 byte boundary - data_size = (footer.parms.num_bytes + 7) & ~0x00000007ul; - - //limit data size - if(data_size > PK_TRACE_CLIPPED_BINARY_SZ) - { - data_size = PK_TRACE_CLIPPED_BINARY_SZ; - } - - //*****The following operations must be done atomically***** - pk_critical_section_enter(&ctx); - - //load in the offset in the cb for the entry we are adding - cb_offset = g_pk_trace_buf.state.offset; - - //Find the offset for the footer (at the end of the entry) - footer_offset = cb_offset + data_size; - - //calculate the address of the footer - ptr64 = (uint64_t*)&g_pk_trace_buf.cb[footer_offset & PK_TRACE_CB_MASK]; - - //calculate the offset for the next entry in the cb - state.offset = footer_offset + sizeof(PkTraceBinary); - - //update the cb state (tbu and offset) - g_pk_trace_buf.state.word64 = state.word64; - - //write the footer data to the circular buffer including the - //timesamp, string hash and data size - *ptr64 = footer.word64; - - //*******************exit the critical section*************** - pk_critical_section_exit(&ctx); - - //write data to the circular buffer - for(src = bufp, index = 0; - index < data_size; - index++) - { - dest = &g_pk_trace_buf.cb[(cb_offset + index) & PK_TRACE_CB_MASK]; - *dest = *(src++); - } - - //Mark the trace entry update as being completed - footer_ptr = (PkTraceBinary*)ptr64; - footer_ptr->parms.complete = 1; - -} - -#endif - - diff --git a/pk/trace/pk_trace_core.c b/pk/trace/pk_trace_core.c deleted file mode 100644 index 429679db..00000000 --- a/pk/trace/pk_trace_core.c +++ /dev/null @@ -1,119 +0,0 @@ -//----------------------------------------------------------------------------- -// *! (C) Copyright International Business Machines Corp. 2014 -// *! All Rights Reserved -- Property of IBM -// *! *** IBM Confidential *** -//----------------------------------------------------------------------------- - -/// \file pk_trace_core.c -/// \brief PK Trace core data and code. -/// -/// This file includes the minimal code/data required to do minimal tracing. -/// This includes the periodic timer initialization and the pk_trace_tiny -/// function. The pk_trace_tiny function is called by the PK_TRACE() macro -/// when there is one or less parameters (not including the format string) -/// and the parameter size is 16 bits or smaller. -/// - -#include "pk.h" -#include "pk_trace.h" - -void pk_trace_timer_callback(void* arg); - -#if (PK_TRACE_SUPPORT && PK_TIMER_SUPPORT) - -//Static initialization of the trace timer -PkTimer g_pk_trace_timer = { - .deque = PK_DEQUE_ELEMENT_INIT(), - .timeout = 0, - .callback = pk_trace_timer_callback, - .arg = 0, -}; - -//Static initialization of the pk trace buffer -PkTraceBuffer g_pk_trace_buf = -{ - .version = PK_TRACE_VERSION, - .image_str = PPE_IMG_STRING, - .hash_prefix = PK_TRACE_HASH_PREFIX, - .partial_trace_hash = trace_ppe_hash("PARTIAL TRACE ENTRY. HASH_ID = %d", PK_TRACE_HASH_PREFIX), - .size = PK_TRACE_SZ, - .max_time_change = PK_TRACE_MTBT, - .hz = 500000000, //default value. Actual value is set in pk_init.c - .time_adj64 = 0, - .state.word64 = 0, - .cb = {0} -}; - -//Needed for buffer extraction in simics for now -PkTraceBuffer* g_pk_trace_buf_ptr = &g_pk_trace_buf; - -// Creates an 8 byte entry in the trace buffer that includes a timestamp, -// a format string hash value and a 16 bit parameter. -// -// i_parm has the hash value combined with the 16 bit parameter -void pk_trace_tiny(uint32_t i_parm) -{ - PkTraceTiny footer; - PkTraceState state; - uint64_t* ptr64; - uint64_t tb64; - PkMachineContext ctx; - - //fill in the footer data - footer.parms.word32 = i_parm; - tb64 = pk_timebase_get(); - state.tbu32 = tb64 >> 32; - footer.time_format.word32 = tb64 & 0x00000000ffffffffull; - - footer.time_format.format = PK_TRACE_FORMAT_TINY; - - //The following operations must be done atomically - pk_critical_section_enter(&ctx); - - //load the current byte count and calculate the address for this - //entry in the cb - ptr64 = (uint64_t*)&g_pk_trace_buf.cb[g_pk_trace_buf.state.offset & PK_TRACE_CB_MASK]; - - //calculate the offset for the next entry in the cb - state.offset = g_pk_trace_buf.state.offset + sizeof(PkTraceTiny); - - //update the cb state (tbu and offset) - g_pk_trace_buf.state.word64 = state.word64; - - //write the data to the circular buffer including the - //timesamp, string hash, and 16bit parameter - *ptr64 = footer.word64; - - //exit the critical section - pk_critical_section_exit(&ctx); -} - - -// This function is called periodically in order to ensure that the max ticks -// between trace entries is no more than what will fit inside a 32bit value. -#ifndef PK_TRACE_TIMER_OUTPUT -#define PK_TRACE_TIMER_OUTPUT 1 -#endif -void pk_trace_timer_callback(void* arg) -{ -#if PK_TRACE_TIMER_OUTPUT - // guarantee at least one trace before the lower 32bit timebase flips - PK_TRACE("PERIODIC TIMESTAMPING TRACE"); -#endif - // restart the timer - pk_timer_schedule(&g_pk_trace_timer, - PK_TRACE_TIMER_PERIOD); -} - -// Use this function to synchronize the timebase between multiple PPEs. -// PPE A can send PPE B it's current timebase and then PPE B can set that -// as the current timebase for tracing purposes. It can also be used -// to set the current time to 0. This function changes the timebase for -// all entries that are currently in the trace buffer. Setting the current -// timebase to 0 will cause previous traces to have very large timestamps. -void pk_trace_set_timebase(PkTimebase timebase) -{ - g_pk_trace_buf.time_adj64 = timebase - pk_timebase_get(); -} - -#endif diff --git a/pk/trace/pktracefiles.mk b/pk/trace/pktracefiles.mk deleted file mode 100644 index e3aede76..00000000 --- a/pk/trace/pktracefiles.mk +++ /dev/null @@ -1,39 +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 -########################################################################## -PKTRACE-C-SOURCES = pk_trace_core.c pk_trace_big.c pk_trace_binary.c - -PKTRACE-S-SOURCES = - -PKTRACE-TIMER-C-SOURCES = -PKTRACE-TIMER-S-SOURCES = - -PKTRACE-THREAD-C-SOURCES += -PKTRACE-THREAD-S-SOURCES += - - -PKTRACE_OBJECTS += $(PKTRACE-C-SOURCES:.c=.o) $(PKTRACE-S-SOURCES:.S=.o) - - - diff --git a/sbe/image/Makefile b/sbe/image/Makefile index 58d77fb2..5ed60626 100644 --- a/sbe/image/Makefile +++ b/sbe/image/Makefile @@ -120,8 +120,8 @@ SIMICS_PPETRACEPP_TAR_FILES += $(PPETRACEPP_DIR)/ppe2fsp.c SIMICS_PPETRACEPP_TAR_FILES += $(PPETRACEPP_DIR)/ppe2fsp_cmd.c SIMICS_PPETRACEPP_TAR_FILES += $(PPETRACEPP_DIR)/trac_interface.h SIMICS_PPETRACEPP_TAR_FILES += $(PK_SRCDIR)/trace/pk_trace.h -SIMICS_PARSERPLUGINS_TAR_FILES += $(PK_SRCDIR)/../sbe/sbefw/plugins/sbeUserDataParser.C -SIMICS_PARSERPLUGINS_TAR_FILES += $(PK_SRCDIR)/../sbe/sbefw/sbeFFDCType.H +SIMICS_PARSERPLUGINS_TAR_FILES += $(SBE_ROOT_DIR)/sbe/sbefw/plugins/sbeUserDataParser.C +SIMICS_PARSERPLUGINS_TAR_FILES += $(SBE_ROOT_DIR)/sbe/sbefw/sbeFFDCType.H SBE_TOOLS := $(TOOLS_IMAGE_DIR)/sbe_default_tool diff --git a/sbe/image/img_defs.mk b/sbe/image/img_defs.mk index 025ab55a..42c12d82 100644 --- a/sbe/image/img_defs.mk +++ b/sbe/image/img_defs.mk @@ -67,6 +67,10 @@ ifndef PPE_TYPE PPE_TYPE := std endif +ifndef SBE_ROOT_DIR +export SBE_ROOT_DIR = $(abspath ../..) +endif + ifndef IMAGE_SRCDIR export IMAGE_SRCDIR = $(abspath .) endif @@ -130,7 +134,7 @@ endif export IMG_OBJDIR = $(BASE_OBJDIR)/$(IMAGE_SEEPROM_NAME) ifndef PK_SRCDIR -export PK_SRCDIR = $(abspath ../../pk) +export PK_SRCDIR = $(abspath ../../import/chips/p9/procedures/ppe/pk) endif @@ -308,9 +312,9 @@ INCLUDES += -I$(PK_SRCDIR)/../include/std INCLUDES += -I$(PK_SRCDIR)/kernel INCLUDES += -I$(PK_SRCDIR)/ppe INCLUDES += -I$(PK_SRCDIR)/ppe42 -INCLUDES += -I$(PK_SRCDIR)/../sbe/sbefw +INCLUDES += -I$(SBE_ROOT_DIR)/sbe/sbefw INCLUDES += -I$(PK_SRCDIR)/trace -INCLUDES += -I$(PK_SRCDIR)/../tools/ppetracepp +INCLUDES += -I$(SBE_ROOT_DIR)/tools/ppetracepp INCLUDES += -I$(IMPORT_COMMON_DIR)/include INCLUDES += -I$(IMPORT_UTILS_DIR)/imageProcs INCLUDES += -I$(IMPORT_UTILS_DIR)/ diff --git a/tools/image/Makefile b/tools/image/Makefile index 412f233a..b1dff574 100644 --- a/tools/image/Makefile +++ b/tools/image/Makefile @@ -55,10 +55,10 @@ INCLUDES += -I ../../sbe/hwpf/include/plat INCLUDES += -I ../../sbe/hwpf/include INCLUDES += -I ../../hwpf/include/plat INCLUDES += -I ../../hwpf/include/ -INCLUDES += -I ../../pk/ppe42/ -INCLUDES += -I ../../pk/kernel/ -INCLUDES += -I ../../pk/std/ -INCLUDES += -I ../../pk/trace/ +INCLUDES += -I ../../import/chips/p9/procedures/ppe/pk/ppe42/ +INCLUDES += -I ../../import/chips/p9/procedures/ppe/pk/kernel/ +INCLUDES += -I ../../import/chips/p9/procedures/ppe/pk/std/ +INCLUDES += -I ../../import/chips/p9/procedures/ppe/pk/trace/ INCLUDES += -I ../../tools/ppetracepp/ INCLUDES += -I ../../import/hwpf/fapi2/include/ INCLUDES += -I ../../import/chips/p9/xip/ diff --git a/tools/ppetracepp/Makefile b/tools/ppetracepp/Makefile index abb4ce92..561297be 100644 --- a/tools/ppetracepp/Makefile +++ b/tools/ppetracepp/Makefile @@ -31,7 +31,7 @@ ppetracepp: ppetracepp.C # g++ -O3 -w -x c++ -fPIC -g -I./ ppetracepp.C -o ppetracepp ppe2fsp: ppe2fsp.c ppe2fsp_cmd.c - gcc -m32 -w -g -I./ -I../../pk/trace ppe2fsp.c ppe2fsp_cmd.c -o $(PPETRACEPP_BIN_DIR)/ppe2fsp + gcc -m32 -w -g -I./ -I../../import/chips/p9/procedures/ppe/pk/trace ppe2fsp.c ppe2fsp_cmd.c -o $(PPETRACEPP_BIN_DIR)/ppe2fsp clean: rm $(PPETRACEPP_BIN_DIR)/ppetracepp $(PPETRACEPP_BIN_DIR)/ppe2fsp -- cgit v1.2.1