summaryrefslogtreecommitdiff
path: root/docs/psci-pd-tree.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/psci-pd-tree.md')
-rw-r--r--docs/psci-pd-tree.md308
1 files changed, 0 insertions, 308 deletions
diff --git a/docs/psci-pd-tree.md b/docs/psci-pd-tree.md
deleted file mode 100644
index a847f06b..00000000
--- a/docs/psci-pd-tree.md
+++ /dev/null
@@ -1,308 +0,0 @@
-PSCI Library Integration guide for ARMv8-A AArch32 systems
-==========================================================
-
-Contents
---------
-
-1. [Requirements](#requirements)
-2. [Design](#design)
-
-------------
-Requirements
-------------
-
-1. A platform must export the `plat_get_aff_count()` and
- `plat_get_aff_state()` APIs to enable the generic PSCI code to
- populate a tree that describes the hierarchy of power domains in the
- system. This approach is inflexible because a change to the topology
- requires a change in the code.
-
- It would be much simpler for the platform to describe its power domain tree
- in a data structure.
-
-2. The generic PSCI code generates MPIDRs in order to populate the power domain
- tree. It also uses an MPIDR to find a node in the tree. The assumption that
- a platform will use exactly the same MPIDRs as generated by the generic PSCI
- code is not scalable. The use of an MPIDR also restricts the number of
- levels in the power domain tree to four.
-
- Therefore, there is a need to decouple allocation of MPIDRs from the
- mechanism used to populate the power domain topology tree.
-
-3. The current arrangement of the power domain tree requires a binary search
- over the sibling nodes at a particular level to find a specified power
- domain node. During a power management operation, the tree is traversed from
- a 'start' to an 'end' power level. The binary search is required to find the
- node at each level. The natural way to perform this traversal is to
- start from a leaf node and follow the parent node pointer to reach the end
- level.
-
- Therefore, there is a need to define data structures that implement the tree in
- a way which facilitates such a traversal.
-
-4. The attributes of a core power domain differ from the attributes of power
- domains at higher levels. For example, only a core power domain can be identified
- using an MPIDR. There is no requirement to perform state coordination while
- performing a power management operation on the core power domain.
-
- Therefore, there is a need to implement the tree in a way which facilitates this
- distinction between a leaf and non-leaf node and any associated
- optimizations.
-
-
-------
-Design
-------
-
-### Describing a power domain tree
-
-To fulfill requirement 1., the existing platform APIs
-`plat_get_aff_count()` and `plat_get_aff_state()` have been
-removed. A platform must define an array of unsigned chars such that:
-
-1. The first entry in the array specifies the number of power domains at the
- highest power level implemented in the platform. This caters for platforms
- where the power domain tree does not have a single root node, for example,
- the FVP has two cluster power domains at the highest level (1).
-
-2. Each subsequent entry corresponds to a power domain and contains the number
- of power domains that are its direct children.
-
-3. The size of the array minus the first entry will be equal to the number of
- non-leaf power domains.
-
-4. The value in each entry in the array is used to find the number of entries
- to consider at the next level. The sum of the values (number of children) of
- all the entries at a level specifies the number of entries in the array for
- the next level.
-
-The following example power domain topology tree will be used to describe the
-above text further. The leaf and non-leaf nodes in this tree have been numbered
-separately.
-
-```
- +-+
- |0|
- +-+
- / \
- / \
- / \
- / \
- / \
- / \
- / \
- / \
- / \
- / \
- +-+ +-+
- |1| |2|
- +-+ +-+
- / \ / \
- / \ / \
- / \ / \
- / \ / \
- +-+ +-+ +-+ +-+
- |3| |4| |5| |6|
- +-+ +-+ +-+ +-+
- +---+-----+ +----+----| +----+----+ +----+-----+-----+
- | | | | | | | | | | | | |
- | | | | | | | | | | | | |
- v v v v v v v v v v v v v
- +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +--+ +--+ +--+
- |0| |1| |2| |3| |4| |5| |6| |7| |8| |9| |10| |11| |12|
- +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +--+ +--+ +--+
-```
-
-
-This tree is defined by the platform as the array described above as follows:
-
-```
- #define PLAT_NUM_POWER_DOMAINS 20
- #define PLATFORM_CORE_COUNT 13
- #define PSCI_NUM_NON_CPU_PWR_DOMAINS \
- (PLAT_NUM_POWER_DOMAINS - PLATFORM_CORE_COUNT)
-
- unsigned char plat_power_domain_tree_desc[] = { 1, 2, 2, 2, 3, 3, 3, 4};
-```
-
-### Removing assumptions about MPIDRs used in a platform
-
-To fulfill requirement 2., it is assumed that the platform assigns a
-unique number (core index) between `0` and `PLAT_CORE_COUNT - 1` to each core
-power domain. MPIDRs could be allocated in any manner and will not be used to
-populate the tree.
-
-`plat_core_pos_by_mpidr(mpidr)` will return the core index for the core
-corresponding to the MPIDR. It will return an error (-1) if an MPIDR is passed
-which is not allocated or corresponds to an absent core. The semantics of this
-platform API have changed since it is required to validate the passed MPIDR. It
-has been made a mandatory API as a result.
-
-Another mandatory API, `plat_my_core_pos()` has been added to return the core
-index for the calling core. This API provides a more lightweight mechanism to get
-the index since there is no need to validate the MPIDR of the calling core.
-
-The platform should assign the core indices (as illustrated in the diagram above)
-such that, if the core nodes are numbered from left to right, then the index
-for a core domain will be the same as the index returned by
- `plat_core_pos_by_mpidr()` or `plat_my_core_pos()` for that core. This
-relationship allows the core nodes to be allocated in a separate array
-(requirement 4.) during `psci_setup()` in such an order that the index of the
-core in the array is the same as the return value from these APIs.
-
-#### Dealing with holes in MPIDR allocation
-
-For platforms where the number of allocated MPIDRs is equal to the number of
-core power domains, for example, Juno and FVPs, the logic to convert an MPIDR to
-a core index should remain unchanged. Both Juno and FVP use a simple collision
-proof hash function to do this.
-
-It is possible that on some platforms, the allocation of MPIDRs is not
-contiguous or certain cores have been disabled. This essentially means that the
-MPIDRs have been sparsely allocated, that is, the size of the range of MPIDRs
-used by the platform is not equal to the number of core power domains.
-
-The platform could adopt one of the following approaches to deal with this
-scenario:
-
-1. Implement more complex logic to convert a valid MPIDR to a core index while
- maintaining the relationship described earlier. This means that the power
- domain tree descriptor will not describe any core power domains which are
- disabled or absent. Entries will not be allocated in the tree for these
- domains.
-
-2. Treat unallocated MPIDRs and disabled cores as absent but still describe them
- in the power domain descriptor, that is, the number of core nodes described
- is equal to the size of the range of MPIDRs allocated. This approach will
- lead to memory wastage since entries will be allocated in the tree but will
- allow use of a simpler logic to convert an MPIDR to a core index.
-
-
-### Traversing through and distinguishing between core and non-core power domains
-
-To fulfill requirement 3 and 4, separate data structures have been defined
-to represent leaf and non-leaf power domain nodes in the tree.
-
-```
-/*******************************************************************************
- * The following two data structures implement the power domain tree. The tree
- * is used to track the state of all the nodes i.e. power domain instances
- * described by the platform. The tree consists of nodes that describe CPU power
- * domains i.e. leaf nodes and all other power domains which are parents of a
- * CPU power domain i.e. non-leaf nodes.
- ******************************************************************************/
-typedef struct non_cpu_pwr_domain_node {
- /*
- * Index of the first CPU power domain node level 0 which has this node
- * as its parent.
- */
- unsigned int cpu_start_idx;
-
- /*
- * Number of CPU power domains which are siblings of the domain indexed
- * by 'cpu_start_idx' i.e. all the domains in the range 'cpu_start_idx
- * -> cpu_start_idx + ncpus' have this node as their parent.
- */
- unsigned int ncpus;
-
- /* Index of the parent power domain node */
- unsigned int parent_node;
-
- -----
-} non_cpu_pd_node_t;
-
-typedef struct cpu_pwr_domain_node {
- u_register_t mpidr;
-
- /* Index of the parent power domain node */
- unsigned int parent_node;
-
- -----
-} cpu_pd_node_t;
-```
-
-The power domain tree is implemented as a combination of the following data
-structures.
-
-```
-non_cpu_pd_node_t psci_non_cpu_pd_nodes[PSCI_NUM_NON_CPU_PWR_DOMAINS];
-cpu_pd_node_t psci_cpu_pd_nodes[PLATFORM_CORE_COUNT];
-```
-
-### Populating the power domain tree
-
-The `populate_power_domain_tree()` function in `psci_setup.c` implements the
-algorithm to parse the power domain descriptor exported by the platform to
-populate the two arrays. It is essentially a breadth-first-search. The nodes for
-each level starting from the root are laid out one after another in the
-`psci_non_cpu_pd_nodes` and `psci_cpu_pd_nodes` arrays as follows:
-
-```
-psci_non_cpu_pd_nodes -> [[Level 3 nodes][Level 2 nodes][Level 1 nodes]]
-psci_cpu_pd_nodes -> [Level 0 nodes]
-```
-
-For the example power domain tree illustrated above, the `psci_cpu_pd_nodes`
-will be populated as follows. The value in each entry is the index of the parent
-node. Other fields have been ignored for simplicity.
-
-```
- +-------------+ ^
- CPU0 | 3 | |
- +-------------+ |
- CPU1 | 3 | |
- +-------------+ |
- CPU2 | 3 | |
- +-------------+ |
- CPU3 | 4 | |
- +-------------+ |
- CPU4 | 4 | |
- +-------------+ |
- CPU5 | 4 | | PLATFORM_CORE_COUNT
- +-------------+ |
- CPU6 | 5 | |
- +-------------+ |
- CPU7 | 5 | |
- +-------------+ |
- CPU8 | 5 | |
- +-------------+ |
- CPU9 | 6 | |
- +-------------+ |
- CPU10 | 6 | |
- +-------------+ |
- CPU11 | 6 | |
- +-------------+ |
- CPU12 | 6 | v
- +-------------+
-```
-
-The `psci_non_cpu_pd_nodes` array will be populated as follows. The value in
-each entry is the index of the parent node.
-
-```
- +-------------+ ^
- PD0 | -1 | |
- +-------------+ |
- PD1 | 0 | |
- +-------------+ |
- PD2 | 0 | |
- +-------------+ |
- PD3 | 1 | | PLAT_NUM_POWER_DOMAINS -
- +-------------+ | PLATFORM_CORE_COUNT
- PD4 | 1 | |
- +-------------+ |
- PD5 | 2 | |
- +-------------+ |
- PD6 | 2 | |
- +-------------+ v
-```
-
-Each core can find its node in the `psci_cpu_pd_nodes` array using the
-`plat_my_core_pos()` function. When a core is turned on, the normal world
-provides an MPIDR. The `plat_core_pos_by_mpidr()` function is used to validate
-the MPIDR before using it to find the corresponding core node. The non-core power
-domain nodes do not need to be identified.
-
-- - - - - - - - - - - - - - - - - - - - - - - - - -
-
-_Copyright (c) 2017, ARM Limited and Contributors. All rights reserved._