summaryrefslogtreecommitdiffstats
path: root/src/include/kernel
diff options
context:
space:
mode:
authorPatrick Williams <iawillia@us.ibm.com>2012-07-31 10:26:12 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2012-08-10 11:38:42 -0500
commit99f217daf307b3cd963bcbce8eb7b025d58f734e (patch)
tree87a82faba5be946460ff25f222f0f10a03afdfce /src/include/kernel
parentda472c60655393f0bb49113713a8be2bdd2a9b6f (diff)
downloadblackbird-hostboot-99f217daf307b3cd963bcbce8eb7b025d58f734e.tar.gz
blackbird-hostboot-99f217daf307b3cd963bcbce8eb7b025d58f734e.zip
Support for master winkle.
RTC: 44730 Change-Id: Ifaeecc659e1bfd8ded4744dc591fc993471519ba Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/1471 Tested-by: Jenkins Server Reviewed-by: Mark W. Wenning <wenning@us.ibm.com> Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/include/kernel')
-rw-r--r--src/include/kernel/cpu.H55
-rw-r--r--src/include/kernel/cpumgr.H43
-rw-r--r--src/include/kernel/deferred.H201
-rw-r--r--src/include/kernel/misc.H29
-rw-r--r--src/include/kernel/ppcconsts.S23
-rw-r--r--src/include/kernel/syscalls.H6
6 files changed, 316 insertions, 41 deletions
diff --git a/src/include/kernel/cpu.H b/src/include/kernel/cpu.H
index e395b2920..2efa89df2 100644
--- a/src/include/kernel/cpu.H
+++ b/src/include/kernel/cpu.H
@@ -1,25 +1,26 @@
-// IBM_PROLOG_BEGIN_TAG
-// This is an automatically generated prolog.
-//
-// $Source: src/include/kernel/cpu.H $
-//
-// IBM CONFIDENTIAL
-//
-// COPYRIGHT International Business Machines Corp. 2010 - 2011
-//
-// p1
-//
-// Object Code Only (OCO) source materials
-// Licensed Internal Code Source Materials
-// IBM HostBoot Licensed Internal Code
-//
-// The source code for this program is not published or other-
-// wise divested of its trade secrets, irrespective of what has
-// been deposited with the U.S. Copyright Office.
-//
-// Origin: 30
-//
-// IBM_PROLOG_END
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/include/kernel/cpu.H $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2010-2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
/** @file cpu.H
* @brief Defines kernel information and functions about CPUs.
*
@@ -42,7 +43,7 @@ class Scheduler;
* @brief Stores per-CPU kernel information.
*
* @note kernel_stack and master need to be at fixed locations in this
- * structure due to usages in start.S.
+ * structure due to usages in start.S (see ppcconsts.S).
*
* - kernel_stack is a double-word at cpu_t[0 bytes].
* - master is a byte at cpu_t[12 bytes].
@@ -63,8 +64,11 @@ struct cpu_t
/** If the CPU is active */
bool active:1;
+ /** If the CPU is winkled */
+ bool winkled:1;
+
/** Ensure alignment of master attribute for asm code. */
- uint64_t __reserved_master:30;
+ uint64_t __reserved_master:29;
} PACKED;
/** Pointer to the scheduler for this CPU (may not be unique) */
@@ -86,6 +90,9 @@ struct cpu_t
/** counter for executePeriodics */
size_t periodic_count;
+
+ /** Sequence ID of CPU initialization. */
+ uint64_t cpu_start_seqid;
};
/** @fn getCpuId
diff --git a/src/include/kernel/cpumgr.H b/src/include/kernel/cpumgr.H
index 8cf6d0fc3..fc7b68547 100644
--- a/src/include/kernel/cpumgr.H
+++ b/src/include/kernel/cpumgr.H
@@ -82,10 +82,39 @@ class CpuManager
*/
static void activateCPU(cpu_t * i_cpu);
+ /** @fn deactivateCPU
+ * Deactivate a cpu to show it is not running.
+ * @param[in] cpu_t the CPU
+ * @post Active flag is off in cpu_t structure.
+ */
+ static void deactivateCPU(cpu_t * i_cpu);
+
/** @fn getCpuCount
- * Return the number of active CPUs.
+ * Return the number of active CPUs.
+ */
+ static size_t getCpuCount() { return cv_cpuSeq & 0xFFFFFFFF; }
+
+ /** @fn getCpuSeqId
+ * Return the current CPU start sequence ID.
+ */
+ static size_t getCpuSeqId() { return cv_cpuSeq >> 32; }
+
+ /** @fn getCpuCountAndSeqId
+ * Atomically retrieve both the current active CPU count and
+ * sequence ID.
+ *
*/
- static size_t getCpuCount() { return cv_cpuCount; }
+ static void getCpuCountAndSeqId(uint32_t& o_count, uint32_t& o_seq)
+ {
+ uint64_t cpuSeq = cv_cpuSeq;
+ o_count = cpuSeq & 0xFFFFFFFF;
+ o_seq = cpuSeq >> 32;
+ }
+
+ /** @fn getThreadCount
+ * Return the number of HW threads for this CPU core type.
+ */
+ static size_t getThreadCount();
/** @fn startCore
* Create structures to support a core activating and start the core.
@@ -127,16 +156,16 @@ class CpuManager
void startCPU(ssize_t i = -1);
void startSlaveCPU(cpu_t*);
- static size_t getThreadCount();
-
private:
static cpu_t** cv_cpus; // Need to be able to access this
// from start.S to get initial stacks
// of secondary cpus / threads.
- static Barrier cv_barrier; //!< barrier for cpus
- static bool cv_defrag; //!< mem heap defrag
- static size_t cv_cpuCount; //!< # of active CPUs
+ /** Number of active CPUs.
+ * Stored as "(seqID << 32) | cpus"
+ */
+ static uint64_t cv_cpuSeq;
+
static bool cv_forcedMemPeriodic; //!< force free / coalesce.
// If a shutdown of all CPUs is requested
diff --git a/src/include/kernel/deferred.H b/src/include/kernel/deferred.H
new file mode 100644
index 000000000..6d8950acb
--- /dev/null
+++ b/src/include/kernel/deferred.H
@@ -0,0 +1,201 @@
+/* IBM_PROLOG_BEGIN_TAG
+ * This is an automatically generated prolog.
+ *
+ * $Source: src/include/kernel/deferred.H $
+ *
+ * IBM CONFIDENTIAL
+ *
+ * COPYRIGHT International Business Machines Corp. 2012
+ *
+ * p1
+ *
+ * Object Code Only (OCO) source materials
+ * Licensed Internal Code Source Materials
+ * IBM HostBoot Licensed Internal Code
+ *
+ * The source code for this program is not published or other-
+ * wise divested of its trade secrets, irrespective of what has
+ * been deposited with the U.S. Copyright Office.
+ *
+ * Origin: 30
+ *
+ * IBM_PROLOG_END_TAG
+ */
+#ifndef __KERNEL_DEFERRED_H
+#define __KERNEL_DEFERRED_H
+
+/** @file deferred.H
+ * @brief Definition of kernel's deferred work constructs.
+ *
+ * These classes allow the kernel to synchronize all CPUs into kernel-mode
+ * and execute a task. These work items are queued up to be executed at
+ * the next time-slice expiration (decrementer exception).
+ */
+
+#include <kernel/types.h>
+#include <kernel/spinlock.H>
+#include <kernel/barrier.H>
+
+/** @class DeferredWork
+ * @brief The base work-item type for deferred work.
+ *
+ * This class implements the synchronization and state transition for a
+ * general deferred work object. This class has methods for defining
+ * the behavior at specific points in its execution. A real behavior
+ * implementation should be defined by inheriting this class and overloading
+ * the desired virtual methods.
+ *
+ * The class is closely associated with the DeferredQueue, which is meant to
+ * hold pending DeferredWork objects. When a DeferredWork is complete it
+ * will remove itself from the DeferredQueue and self-delete.
+ *
+ * The state transition is as follows:
+ *
+ * <pre>
+ * MASTER Both NON-MASTER
+ * 1. Sync all
+ * 2. masterPreWork block
+ * 3. activeMainWork
+ * 4. Sync all
+ * 5. masterPostWork block
+ * 6. Last thread out deletes
+ * </pre>
+ *
+ * With the deferred work there is concern as to what to do with CPUs that
+ * come online while a deferred work item is being executed. For instance,
+ * the Heap Coalescing work could cause data integrity issues if a freshly
+ * activated CPU were to not block with the rest of the CPUs and instead
+ * started executed user-space code. To deal with this condition a
+ * CPU which is activated after the DeferredWork object was created will
+ * block at masterPreWork and masterPostWork stages and call
+ * nonactiveMainWork. Typically, the non-active CPUs perform no action
+ * but an implementation could assert for a race-condition that cannot
+ * be handled properly (though should never occur).
+ */
+class DeferredWork
+{
+ public:
+ /** Default Constructor
+ * Initializes the work item and determines the CPU-activation
+ * sequence number at the time of creation.
+ */
+ DeferredWork();
+
+ /** Default destructor
+ * Verifies that the work item has completed properly and is
+ * detached from the DeferredQueue.
+ */
+ virtual ~DeferredWork();
+
+ /** Entry point for DeferredWork execution. */
+ void start();
+
+ protected:
+ // Functions to override for desired behavior:
+ /** Executed by master before "main" but after all active
+ * CPUs are sync'd.
+ */
+ virtual void masterPreWork() {};
+ /** Executed by master after "main" work is complete. */
+ virtual void masterPostWork() {};
+ /** Executed by all [active] CPUs as the "main" work. */
+ virtual void activeMainWork() {};
+ /** Executed by all non-active CPUs as the "main" work. */
+ virtual void nonactiveMainWork() {};
+
+ private:
+ friend class DeferredQueue;
+
+ /** Barrier for synchronization of active CPUs. */
+ Barrier iv_barrier;
+ /** Count of CPUs in object and pointer to next object.
+ *
+ * Stored as "(cpu count << 32) | (DeferredWork* next)". This
+ * is done so that we can atomically check and/or set both
+ * values.
+ */
+ volatile uint64_t iv_cpus_and_next;
+ /** Sequence ID at the time of creation. */
+ uint32_t iv_activeSeqId;
+ /** Boolean to indicate masterPreWork is complete. */
+ volatile bool iv_releasePre;
+ /** Boolean to indicate masterPostWork is complete. */
+ volatile bool iv_releasePost;
+
+ // Internal state transition functions.
+ void _waitForCpus();
+ void _masterPre();
+ void _waitAtPre();
+ void _masterPost();
+ void _waitAtPost();
+ void _cleanup();
+
+};
+
+/** @class DeferredQueue
+ * @brief Queue for DeferredWork objects.
+ *
+ * This class should have a Singleton instance for the whole kernel.
+ * Periodically, kernel threads can call the 'execute' function to execute
+ * pending work, if any is available. Additional work can be 'insert'ed.
+ */
+class DeferredQueue
+{
+ public:
+ /** Default constructor. */
+ DeferredQueue();
+ /** Default destructor. */
+ ~DeferredQueue();
+
+ /** Insert a work item into the queue.
+ *
+ * @param i_work - The item to add.
+ *
+ * Ownership of the work item is transfered to the queue, which is
+ * responsible for delete once the work is complete.
+ */
+ static void insert(DeferredWork* i_work);
+ /** Execute any pending work items. */
+ static void execute();
+
+ private:
+ friend class DeferredWork;
+
+ // Instance functions for static pair.
+ void _insert(DeferredWork* i_work);
+ void _execute();
+
+ /** Remove a completed work item from the queue.
+ *
+ * This function is to be called by the master CPU executing the
+ * work item being completed.
+ *
+ * The work item is atomically removed from the queue and the
+ * count of CPUs with a pointer to the work item is compared
+ * against the count of CPUs in the work item. This function
+ * returns when all CPUs that have a pointer are actually inside
+ * the work item (so we can accurately determine when there is
+ * only a single CPU in the work item for delete).
+ *
+ * @param i_work - The item to remove.
+ */
+ void _complete(DeferredWork* i_work);
+
+ /** Spinlock to protect insert / remove operations.
+ *
+ * This is effectively a "write" lock on the structure and all
+ * reads are done atomically. The writers have also use atomic
+ * update operations to ensure the readers (which are never
+ * locked) operate in a thread-safe manner.
+ */
+ Spinlock lock;
+ /** Count of CPUs in first object and pointer to it.
+ *
+ * Stored as "(cpu count << 32) | (DeferredWork* ptr)". This
+ * is done so that we can atomically check and/or set both
+ * values.
+ */
+ volatile uint64_t iv_cpus_and_next;
+};
+
+#endif
diff --git a/src/include/kernel/misc.H b/src/include/kernel/misc.H
index ebec9cc48..c970c337e 100644
--- a/src/include/kernel/misc.H
+++ b/src/include/kernel/misc.H
@@ -30,6 +30,8 @@
#include <stdint.h>
#include <usr/vmmconst.h>
+#include <kernel/deferred.H>
+#include <kernel/task.H>
namespace KernelMisc
{
@@ -59,5 +61,32 @@ namespace KernelMisc
}
return true;
}
+
+ /** @class WinkleCore
+ *
+ * @brief DeferredWork class for implementing cpu_master_winkle.
+ */
+ class WinkleCore : public ::DeferredWork
+ {
+ public:
+ /** ctor
+ *
+ * @param i_caller - Task calling cpu_master_winkle to be
+ * restored after winkle is complete.
+ */
+ WinkleCore(task_t* i_caller) :
+ iv_caller(i_caller), iv_timebase(0) {};
+
+ void masterPreWork();
+ void activeMainWork();
+ void masterPostWork();
+ void nonactiveMainWork();
+
+ private:
+ /** Caller of cpu_master_winkle() */
+ task_t* iv_caller;
+ /** Current time-base value for restore after winkle. */
+ uint64_t iv_timebase;
+ };
};
#endif
diff --git a/src/include/kernel/ppcconsts.S b/src/include/kernel/ppcconsts.S
index 1568bb911..8b84e9135 100644
--- a/src/include/kernel/ppcconsts.S
+++ b/src/include/kernel/ppcconsts.S
@@ -1,24 +1,24 @@
# IBM_PROLOG_BEGIN_TAG
# This is an automatically generated prolog.
-#
+#
# $Source: src/include/kernel/ppcconsts.S $
-#
+#
# IBM CONFIDENTIAL
-#
+#
# COPYRIGHT International Business Machines Corp. 2010-2012
-#
+#
# p1
-#
+#
# Object Code Only (OCO) source materials
# Licensed Internal Code Source Materials
# IBM HostBoot Licensed Internal Code
-#
+#
# The source code for this program is not published or other-
# wise divested of its trade secrets, irrespective of what has
# been deposited with the U.S. Copyright Office.
-#
+#
# Origin: 30
-#
+#
# IBM_PROLOG_END_TAG
#*--------------------------------------------------------------------*#
#* Register Constants *#
@@ -243,3 +243,10 @@
.set TASK_FPR_31, TASK_FPR_30+8
.set TASK_FPSCR, TASK_FPR_31+8
+.set CPU_KERNEL_STACK, 0
+.set CPU_CPUID, CPU_KERNEL_STACK+8
+.set CPU_STATUS, CPU_CPUID+4
+
+.set CPU_STATUS_MASTER, 0
+.set CPU_STATUS_ACTIVE, CPU_STATUS_MASTER+1
+.set CPU_STATUS_WINKLED, CPU_STATUS_ACTIVE+1
diff --git a/src/include/kernel/syscalls.H b/src/include/kernel/syscalls.H
index 5523fc158..b02fd2216 100644
--- a/src/include/kernel/syscalls.H
+++ b/src/include/kernel/syscalls.H
@@ -92,8 +92,10 @@ namespace Systemcalls
MISC_CPUSTARTCORE,
/** cpu_spr_value() */
MISC_CPUSPRVALUE,
- /** cpu_doze() - Hidden syscall */
- MISC_CPUDOZE,
+ /** cpu_nap() - Hidden syscall */
+ MISC_CPUNAP,
+ /** cpu_master_winkle() */
+ MISC_CPUWINKLE,
/** mm_alloc_block() */
MM_ALLOC_BLOCK,
OpenPOWER on IntegriCloud