[RFC PATCH v2 0/2] ARM: MPIDR linearization
Lorenzo Pieralisi
lorenzo.pieralisi at arm.com
Tue Jun 11 05:58:48 EDT 2013
Hi Russell, all,
even though I think this set is ready to get merged, it would be great
if we can test it on as many platforms as possible since it touches core
suspend/resume operations on ARM platforms relying on CONFIG_ARM_CPU_SUSPEND,
and there are many.
I pushed out a branch:
git://linux-arm.org/linux-2.6-lp.git mpidr-linearization
if anyone has time to test the set that would be really great, thank you
very much.
Comments and further review appreciated.
Thanks a lot,
Lorenzo
On Thu, Jun 06, 2013 at 04:22:03PM +0100, Lorenzo Pieralisi wrote:
> This patchset is v2 of a previous posting:
>
> http://lists.infradead.org/pipermail/linux-arm-kernel/2013-June/172873.html
>
> v2 changes:
>
> - rescheduled registers usage in compute_mpidr_hash macro
>
> Cores in ARM SMP systems are identified through coprocessor registers,
> so that every core, by executing a coprocessor read, can detect its own
> identifier. The CPU identifier evolved from a simple CPU ID on ARM 11 MPcore
> SMP, where the CPU ID was split in two subfields (CPU ID and CLUSTER ID)
> to the v7 MPIDR, where the MPIDR[23:0] bits define three affinity levels
> that can describe thread, core, cluster topology identifiers.
> According to the ARM 11 MPcore TRM and for architecture versions later
> than v7 (MPIDR), to the ARM ARM, the identifier registers format is as follows:
>
> NR: non-relevant for identification
>
> ARM11 MPCORE: CPU ID register
>
> 31 12 11 8 7 4 3 0
> ---------------------------------------------------------------------------
> | NR | CLUSTER ID | NR | CPU ID |
> --------------------------------------------------------------------------
>
> ARM v7: MPIDR
>
> 31 24 23 16 15 8 7 0
> ---------------------------------------------------------------------------
> | NR | AFFINITY 2 | AFFINITY 1 | AFFINITY 0 |
> ---------------------------------------------------------------------------
>
> The split of CPU identifiers in multiple affinity levels implies that
> the CPU ID, and later the MPIDR, cannot be used as simple indexes, since
> the bit representation can contain holes:
>
> eg 4 CPUs, in two separate clusters with two CPUs each:
>
> CPU0: MPIDR = 0x0
> CPU1: MPIDR = 0x1
> CPU2: MPIDR = 0x100
> CPU3: MPIDR = 0x101
>
> In order to carry out operations that rely on the HW CPUID/MPIDR (CCI
> disabling, context save/restore) the association of the CPU ID, or MPIDR
> to an index is needed so that the CPU can be associated with a set of
> resources. Resources look-up through the HW CPU ID is carried out in
> code paths usually executed in power down procedures, that have to be
> fast and look-up should be performed with few instructions that may be
> executing in physical address space, with the MMU off.
> In order to provide a fast conversion from [CPU ID, MPIDR] values to indexes
> this set provides methods to build a simple collision-free hash function based
> on shifting and OR'ing of CPU ID values, with shifts precomputed at boot by
> scanning the cpu_logical_map entries (that contain the CPUID/MPIDR) of
> possible CPUs.
>
> By scanning the cpu_logical_map, the boot code detects how many bits are really
> required to represent HW identifiers in the system and map them to a set of
> buckets that actually represent the given index a HW id correspond to. The
> hashing algorithm inherently takes advantage of a-priori knowledge of the
> CPUIDs/MPIDRs allowed bits layout and it can be executed with few instructions
> even in code paths where caching and the MMU are turned off (e.g resuming from
> idle, S2R, hibernation).
>
> One drawback of the current hashing algorithm is that it may result in a big
> number of buckets if the recommendations on the CPUID/MPIDR layout are not
> respected in the CPUID/MPIDR configuration; code warns on hash table
> sizes bigger than 4 times the number of possible CPUs, which is a
> symptom of a weird CPUID/MPIDR HW configuration and should be the exception
> not the rule.
>
> The first patch in the series provides a function that precomputes all
> required hashing parameters by scanning the cpu_logical_map (that
> contains HW identifiers), computes and stashes the hash parameters in a
> structure exported to all kernel components for further usage.
>
> The second patch fixes the current cpu_{suspend}/{resume} functionality,
> so that all levels of CPUID/MPIDR are supported and cpu_{suspend}/{resume}
> can be used on systems where affinity levels 1 and 2 are actually populated.
> The fix carries out dynamic allocation of the array used to save the context
> pointers, with size equal to the number of precomputed CPUID/MPIDR hash
> buckets. To access the array, the CPUID/MPIDR values are hashed through the
> algorithm built in patch 1 so that a hash value is retrieved and the array can
> be indexed properly through it.
>
> Context pointer array is allocated through kmalloc, so that it is made
> up of a contiguous chunk of memory whose virtual address can be safely
> converted to physical address (used in the MMU off path) through a
> static mapping translation valid for all pages (if more than one) making
> up the context pointer array. Context pointer array base address is
> stashed in a structure easily retrieved in assembly through a pc relative
> load that provides both virtual and physical address so that address
> translation is not needed in the cpu_resume path, saving a few instructions.
>
> Code will be improved later through dynamic patching so that the mask
> and shifts in the hashing algorithm will be embedded in the assembly
> instructions as immediates, removing the need for multiple loads to
> memory to retrieve them at every given cpu_{suspend}/{resume} cycle.
>
> Tested on TC2 (dual cluster 2x3 A15/A7 system) through CPU idle deep C-states
> allowing A15 and A7 shutdown modes on both SMP and UP configurations.
>
> Lorenzo Pieralisi (2):
> ARM: kernel: build MPIDR hash function data structure
> ARM: kernel: implement stack pointer save array through MPIDR hashing
>
> arch/arm/include/asm/smp_plat.h | 18 ++++++++
> arch/arm/include/asm/suspend.h | 5 +++
> arch/arm/kernel/asm-offsets.c | 6 +++
> arch/arm/kernel/setup.c | 67 ++++++++++++++++++++++++++++
> arch/arm/kernel/sleep.S | 97 +++++++++++++++++++++++++++++++++--------
> arch/arm/kernel/suspend.c | 20 +++++++++
> 6 files changed, 195 insertions(+), 18 deletions(-)
>
> --
> 1.8.2.2
>
More information about the linux-arm-kernel
mailing list