[PATCH 1/2] armv8: Disable pointer authentication traps for EL1
Andre Przywara
andre.przywara at arm.com
Thu Aug 19 17:17:55 CEST 2021
On 8/13/21 1:22 PM, Peter Hoyes wrote:
Hi,
> From: Peter Hoyes <Peter.Hoyes at arm.com>
>
> The use of ARMv8.3 pointer authentication (PAuth) is governed by fields
> in HCR_EL2, which trigger a 'trap to EL2' if not enabled. The reset
> value of these fields is 'architecturally unknown' so we must ensure
> that the fields are enabled (to disable the traps) if we are entering
> the kernel at EL1.
>
> The APK field disables PAuth instruction traps and the API field
> disables PAuth register traps
>
> Add code to disable the traps in armv8_switch_to_el1_m. Prior to doing
> so, it checks fields in the ID_AA64ISAR1_EL1 register to ensure pointer
> authentication is supported by the hardware.
>
> The runtime checks require a second temporary register, so add this to
> the EL1 transition macro signature and update 2 call sites.
>
> Signed-off-by: Peter Hoyes <Peter.Hoyes at arm.com>
> ---
> arch/arm/cpu/armv8/fsl-layerscape/spintable.S | 2 +-
> arch/arm/cpu/armv8/transition.S | 2 +-
> arch/arm/include/asm/macro.h | 11 +++++++++--
> arch/arm/include/asm/system.h | 15 +++++++++++++++
> 4 files changed, 26 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm/cpu/armv8/fsl-layerscape/spintable.S b/arch/arm/cpu/armv8/fsl-layerscape/spintable.S
> index 363ded03e6..d6bd188459 100644
> --- a/arch/arm/cpu/armv8/fsl-layerscape/spintable.S
> +++ b/arch/arm/cpu/armv8/fsl-layerscape/spintable.S
> @@ -93,7 +93,7 @@ __secondary_boot_func:
> 4:
> #ifdef CONFIG_ARMV8_SWITCH_TO_EL1
> switch_el x7, _dead_loop, 0f, _dead_loop
> -0: armv8_switch_to_el1_m x4, x6, x7
> +0: armv8_switch_to_el1_m x4, x6, x7, x9
> #else
> switch_el x7, 0f, _dead_loop, _dead_loop
> 0: armv8_switch_to_el2_m x4, x6, x7
> diff --git a/arch/arm/cpu/armv8/transition.S b/arch/arm/cpu/armv8/transition.S
> index a31af4ffc8..9dbdff3a4f 100644
> --- a/arch/arm/cpu/armv8/transition.S
> +++ b/arch/arm/cpu/armv8/transition.S
> @@ -40,7 +40,7 @@ ENTRY(armv8_switch_to_el1)
> * now, jump to the address saved in x4.
> */
> br x4
> -1: armv8_switch_to_el1_m x4, x5, x6
> +1: armv8_switch_to_el1_m x4, x5, x6, x7
> ENDPROC(armv8_switch_to_el1)
> .popsection
>
> diff --git a/arch/arm/include/asm/macro.h b/arch/arm/include/asm/macro.h
> index 485310d660..e1eefc283f 100644
> --- a/arch/arm/include/asm/macro.h
> +++ b/arch/arm/include/asm/macro.h
> @@ -256,7 +256,7 @@ lr .req x30
> * For loading 64-bit OS, x0 is physical address to the FDT blob.
> * They will be passed to the guest.
> */
> -.macro armv8_switch_to_el1_m, ep, flag, tmp
> +.macro armv8_switch_to_el1_m, ep, flag, tmp, tmp2
> /* Initialize Generic Timers */
> mrs \tmp, cnthctl_el2
> /* Enable EL1 access to timers */
> @@ -306,7 +306,14 @@ lr .req x30
> b.eq 1f
>
> /* Initialize HCR_EL2 */
> - ldr \tmp, =(HCR_EL2_RW_AARCH64 | HCR_EL2_HCD_DIS)
> + /* Only disable PAuth traps if PAuth is supported */
> + mrs \tmp, id_aa64isar1_el1
> + ldr \tmp2, =(ID_AA64ISAR1_EL1_GPI | ID_AA64ISAR1_EL1_GPA | \
> + ID_AA64ISAR1_EL1_API | ID_AA64ISAR1_EL1_APA)
So I don't know how people feel about this, but we can drop the
additional register at the cost of a bit more code (splitting the test
in two) and some shifting.
But actually I think we have reached the point where this should still
be a macro. Are there are reasons this cannot be a function? We seem to
end with an eret, so the content of LR should not matter?
Cheers,
Andre
> + tst \tmp, \tmp2
> + mov \tmp2, #(HCR_EL2_RW_AARCH64 | HCR_EL2_HCD_DIS)
> + orr \tmp, \tmp2, #(HCR_EL2_APK | HCR_EL2_API)
> + csel \tmp, \tmp2, \tmp, eq
> msr hcr_el2, \tmp
>
> /* Return to the EL1_SP1 mode from EL2 */
> diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
> index 8b3a54e64c..77aa18909e 100644
> --- a/arch/arm/include/asm/system.h
> +++ b/arch/arm/include/asm/system.h
> @@ -75,10 +75,25 @@
> /*
> * HCR_EL2 bits definitions
> */
> +#define HCR_EL2_API (1 << 41) /* Trap pointer authentication
> + instructions */
> +#define HCR_EL2_APK (1 << 40) /* Trap pointer authentication
> + key access */
> #define HCR_EL2_RW_AARCH64 (1 << 31) /* EL1 is AArch64 */
> #define HCR_EL2_RW_AARCH32 (0 << 31) /* Lower levels are AArch32 */
> #define HCR_EL2_HCD_DIS (1 << 29) /* Hypervisor Call disabled */
>
> +/*
> + * ID_AA64ISAR1_EL1 bits definitions
> + */
> +#define ID_AA64ISAR1_EL1_GPI (0xF << 28) /* Implementation-defined generic
> + code auth algorithm */
> +#define ID_AA64ISAR1_EL1_GPA (0xF << 24) /* QARMA generic code auth
> + algorithm */
> +#define ID_AA64ISAR1_EL1_API (0xF << 8) /* Implementation-defined address
> + auth algorithm */
> +#define ID_AA64ISAR1_EL1_APA (0xF << 4) /* QARMA address auth algorithm */
> +
> /*
> * ID_AA64PFR0_EL1 bits definitions
> */
>
More information about the U-Boot
mailing list