PSCI

An overview of PSCI

If you boot a 64-bit kernel on an ARMv8-A platform, you’ll probably notice some output relating to PSCI. In this post, we’re going to explore what this is and why it’s there.

The Power State Coordination Interface (PSCI) is an ARM standard that describes a software interface for power management between an operating system (not just Linux) and it’s supervisory firmware. The interface allows an operating system to perform power management tasks such as putting CPUs into an idle (low-power) state, bringing CPUs online/offline and turning the system off.

You may be wondering why any of this is needed – if you’re familiar with other platforms (e.g. 32-bit ARM) then you’ll know that the kernel would normally directly perform these power management tasks. However such code is often very platform specific and full of quirks – making it difficult to upstream and fit into kernel frameworks. Thus the introduction of the 64-bit Linux kernel was an opportunity to start afresh and to apply lessons learnt from the 32-bit kernel. A common interface not only allows the kernel to abstract all the nastiness of platform-specific code to firmware but it also turns out PSCI solves other problems too.

The software running on modern day ARMv8-A devices is varied but typically layered – often with each layer of software running at a different ARM privilege level and different security state (secure and non-secure). The software may contain a hypervisor and perform virtualisation, utilise a trusted OS and/or run an operating system such as Linux either as a guest or natively. By using an interface such as PSCI, these components can perform power management tasks without consideration to the context they are running in by simply communicating with whoever is going to respond to its PSCI requests. Standard interfaces such as PSCI also allows ARM platforms to become ‘more boring‘ in the sense that operating systems won’t need to be built specifically for a given ARM platform – much like PC’s.

We tend to use the phrase ‘supervisory firmware’ or just ‘firmware’ to refer to the component that responds to PSCI requests – in many cases it’s the Arm Trust Firmware (ATF) software which provides the implementation of PSCI from the secure-world.

The mechanism (or conduit) that is used to allow software to make a PSCI call to firmware is described in the SMC Calling Convention – however it’s essentially a function call that makes use of an SMC or HVC ARM instruction to generate an exception that allows for moving from the current privilege level and security state into the state of the software that provides the PSCI interface (e.g. a hypervisor or ATF). This is very similar to the way system calls are handled.

Let’s take a look at the PSCI output shown at the start of a typical kernel boot:

[    0.000000] psci: probing for conduit method from DT.                                                                                                                                                                              
[    0.000000] psci: PSCIv1.1 detected in firmware.                                                                                                                                                                                   
[    0.000000] psci: Using standard PSCI v0.2 function IDs                                                                                                                                                                            
[    0.000000] psci: MIGRATE_INFO_TYPE not supported.                                                                                                                                                                                 
[    0.000000] psci: SMC Calling Convention v1.1   

When the kernel boot it needs to know how to make a PSCI call – it can get this information from one of two places: the device tree, or via ACPI. In our example above you’ll see that it is obtaining it from the device tree (see function get_set_conduit_method). Here is the matching device tree node – you’ll notice the ‘method’ property is ‘smc’.

        psci {
                compatible = "arm,psci-1.0";
                method = "smc";
        };

The kernel will then make its first PSCI call – it does this to determine the version of PSCI available – in our case it’s PSCIv1.1 as shown in the previous output. Here is the associated kernel code:

static u32 psci_get_version(void)
{
        return invoke_psci_fn(PSCI_0_2_FN_PSCI_VERSION, 0, 0, 0);
}

invoke_psci_fn is a function pointer that either points to a SMC or HVC function that can make a PSCI call. Let’s look at the SMC one:

static unsigned long __invoke_psci_fn_smc(unsigned long function_id,
                        unsigned long arg0, unsigned long arg1,
                        unsigned long arg2)
{
        struct arm_smccc_res res;

        arm_smccc_smc(function_id, arg0, arg1, arg2, 0, 0, 0, 0, &res);
        return res.a0;
}

And finally arm_smcc_smc is a simple assembly macro that unsurprisingly uses the SMC instruction.

The PSCI output also showed “Using standard PSCI v0.2 function IDs” – the SMC or HVC calls specify the function they wish to invoke to PSCI by referencing a unique number – this line of output indicates we’re using the standard numbering for the 0.2 version of PSCI.

The next line “psci: MIGRATE_INFO_TYPE not supported.” relates to the handling of any Trusted OS that may be running. Trusted OS’s typically run on a single core, yet Linux may wish to turn off that core – therefore PSCI offers functionality to migrate a Trusted OS from one core to another. This line of output indicates that, on this platform, migration isn’t supported by the Trusted OS.

And finally, the last line of output describes the calling convention supported by the PSCI.

PSCI is the de-facto firmware interface for providing power management operations on 64-bit ARM devices. And as a result this creates a firmware dependency on systems that wish to boot a 64-bit ARM kernel – fortunately this dependency can usually be satisfied by making use of ATF. You can actually boot a system without PSCI – in a previous post, we’ve seen what happens when a Raspberry Pi is booted without ATF/PSCI and the issues it caused.

Popular Posts