From 58fadd62beba8e9fefddae884bfd34f71a183997 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Igor=20Podgain=C3=B5i?= Date: Fri, 15 Nov 2024 15:20:50 +0100 Subject: [PATCH] fix: add support for 128-bit sysregs to EL3 crash handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The following changes have been made: * Add new sysreg definitions and ASM macro is_feat_sysreg128_present_asm * Add registers TTBR0_EL2 and VTTBR_EL2 to EL3 crash handler output * Use MRRS instead of MRS for registers TTBR0_EL1, TTBR0_EL2, TTBR1_EL1, VTTBR_EL2 and PAR_EL1 Change-Id: I0e20b2c35251f3afba2df794c1f8bc0c46c197ff Signed-off-by: Igor Podgainõi --- bl31/aarch64/crash_reporting.S | 163 +++++++++++++++++++++------ include/arch/aarch64/arch.h | 10 +- include/arch/aarch64/asm_macros.S | 16 ++- lib/extensions/sysreg128/sysreg128.S | 23 ++-- 4 files changed, 160 insertions(+), 52 deletions(-) diff --git a/bl31/aarch64/crash_reporting.S b/bl31/aarch64/crash_reporting.S index 4cec1103e..b5bf5759f 100644 --- a/bl31/aarch64/crash_reporting.S +++ b/bl31/aarch64/crash_reporting.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2023, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2025, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -41,14 +41,25 @@ el3_sys_regs: "daif", "mair_el3", "spsr_el3", "elr_el3", "ttbr0_el3",\ "esr_el3", "far_el3", "" -non_el3_sys_regs: +non_el3_sys_regs_1: .asciz "spsr_el1", "elr_el1", "spsr_abt", "spsr_und",\ "spsr_irq", "spsr_fiq", "sctlr_el1", "actlr_el1", "cpacr_el1",\ - "csselr_el1", "sp_el1", "esr_el1", "ttbr0_el1", "ttbr1_el1",\ - "mair_el1", "amair_el1", "tcr_el1", "tpidr_el1", "tpidr_el0",\ - "tpidrro_el0", "par_el1", "mpidr_el1", "afsr0_el1", "afsr1_el1",\ - "contextidr_el1", "vbar_el1", "cntp_ctl_el0", "cntp_cval_el0",\ - "cntv_ctl_el0", "cntv_cval_el0", "cntkctl_el1", "sp_el0", "isr_el1", "" + "csselr_el1", "sp_el1", "esr_el1", "" + +ttbr_regs: + .asciz "ttbr0_el1", "ttbr0_el2", "ttbr1_el1", "vttbr_el2", "" + +non_el3_sys_regs_2: + .asciz "mair_el1", "amair_el1", "tcr_el1", "tpidr_el1",\ + "tpidr_el0", "tpidrro_el0", "" + +par_reg: + .asciz "par_el1", "" + +non_el3_sys_regs_3: + .asciz "mpidr_el1", "afsr0_el1", "afsr1_el1", "contextidr_el1",\ + "vbar_el1", "cntp_ctl_el0", "cntp_cval_el0", "cntv_ctl_el0",\ + "cntv_cval_el0", "cntkctl_el1", "sp_el0", "isr_el1", "" #if CTX_INCLUDE_AARCH32_REGS aarch32_regs: @@ -71,9 +82,22 @@ excpt_msg_el: * The print loop is controlled by the buf size and * ascii reg name list which is passed in x6. The * function returns the crash buf address in x0. - * Clobbers : x0 - x7, sp + * Clobbers : x0 - x7, x20, sp */ -func size_controlled_print +func size_controlled_print_helper +#if ENABLE_FEAT_D128 +size_controlled_print_128: + /* Set flag to print 128-bit registers */ + mov x20, #1 + b 1f + +size_controlled_print: + /* Set flag to print 64-bit registers */ + mov x20, #0 +1: +#else +size_controlled_print: +#endif /* Save the lr */ mov sp, x30 /* load the crash buf address */ @@ -96,14 +120,22 @@ test_size_list: /* update x6 with the updated list pointer */ mov x6, x4 bl print_alignment + /* Print the high 64 bits (or whole 64-bit register) */ ldr x4, [x7], #REGSZ bl asm_print_hex +#if ENABLE_FEAT_D128 + cbz x20, 2f + /* Print the low 64 bits in case of a 128-bit register */ + ldr x4, [x7], #REGSZ + bl asm_print_hex +2: +#endif bl asm_print_newline b test_size_list exit_size_print: mov x30, sp ret -endfunc size_controlled_print +endfunc size_controlled_print_helper /* ----------------------------------------------------- * This function calculates and prints required number @@ -126,7 +158,7 @@ endfunc print_alignment * copied to the crash buf by this function. * x0 points to the crash buf. It then calls * size_controlled_print to print to console. - * Clobbers : x0 - x7, sp + * Clobbers : x0 - x7, x20, sp */ func str_in_crash_buf_print /* restore the crash buf address in x0 */ @@ -138,6 +170,23 @@ func str_in_crash_buf_print b size_controlled_print endfunc str_in_crash_buf_print + /* + * An equivalent helper function for storing x8 - x15 + * registers in a different order inside the crash buf. + * In the end the function size_controlled_print_128 is + * called to print the registers to the console. + * Clobbers : x0 - x7, x20, sp + */ +func str_in_crash_buf_print_128 + /* restore the crash buf address in x0 */ + mrs x0, tpidr_el3 + stp x8, x9, [x0] + stp x10, x11, [x0, #REGSZ * 2] + stp x12, x13, [x0, #REGSZ * 4] + stp x14, x15, [x0, #REGSZ * 6] + b size_controlled_print_128 +endfunc str_in_crash_buf_print_128 + /* ------------------------------------------------------ * This macro calculates the offset to crash buf from * cpu_data and stores it in tpidr_el3. It also saves x0 @@ -320,7 +369,9 @@ func report_el3_panic * - Print el3 sys regs (in groups of 8 registers) using the * crash buf to the crash console. * - Print non el3 sys regs (in groups of 8 registers) using - * the crash buf to the crash console. + * the crash buf to the crash console. A group may be + * interrupted in case a potential group of 128-bit + * sys regs needs to be printed. * ------------------------------------------------------------ */ do_crash_reporting: @@ -396,7 +447,7 @@ print_el3_sys_regs: bl str_in_crash_buf_print /* Print the non el3 sys registers */ - adr x6, non_el3_sys_regs + adr x6, non_el3_sys_regs_1 mrs x8, spsr_el1 mrs x9, elr_el1 mrs x10, spsr_abt @@ -410,30 +461,74 @@ print_el3_sys_regs: mrs x9, csselr_el1 mrs x10, sp_el1 mrs x11, esr_el1 - mrs x12, ttbr0_el1 - mrs x13, ttbr1_el1 - mrs x14, mair_el1 - mrs x15, amair_el1 bl str_in_crash_buf_print - mrs x8, tcr_el1 - mrs x9, tpidr_el1 - mrs x10, tpidr_el0 - mrs x11, tpidrro_el0 - mrs x12, par_el1 - mrs x13, mpidr_el1 - mrs x14, afsr0_el1 - mrs x15, afsr1_el1 + + adr x6, ttbr_regs +#if ENABLE_FEAT_D128 + is_feat_sysreg128_present_asm x19 + /* Fallback to 64-bit if FEAT_SYSREG128 is disabled */ + cbz x19, ttbr_regs_64_bit + bl read_ttbr0_el1 + mov x8, x1 + mov x9, x0 + bl read_ttbr0_el2 + mov x10, x1 + mov x11, x0 + bl read_ttbr1_el1 + mov x12, x1 + mov x13, x0 + bl read_vttbr_el2 + mov x14, x1 + mov x15, x0 + bl str_in_crash_buf_print_128 + b 1f + +ttbr_regs_64_bit: +#endif + mrs x8, ttbr0_el1 + mrs x9, ttbr0_el2 + mrs x10, ttbr1_el1 + mrs x11, vttbr_el2 bl str_in_crash_buf_print - mrs x8, contextidr_el1 - mrs x9, vbar_el1 - mrs x10, cntp_ctl_el0 - mrs x11, cntp_cval_el0 - mrs x12, cntv_ctl_el0 - mrs x13, cntv_cval_el0 - mrs x14, cntkctl_el1 - mrs x15, sp_el0 +1: + adr x6, non_el3_sys_regs_2 + mrs x8, mair_el1 + mrs x9, amair_el1 + mrs x10, tcr_el1 + mrs x11, tpidr_el1 + mrs x12, tpidr_el0 + mrs x13, tpidrro_el0 bl str_in_crash_buf_print - mrs x8, isr_el1 + + adr x6, par_reg +#if ENABLE_FEAT_D128 + /* Fallback to 64-bit if FEAT_SYSREG128 is disabled */ + cbz x19, par_reg_64_bit + bl read_par_el1 + mov x8, x1 + mov x9, x0 + bl str_in_crash_buf_print_128 + b 2f + +par_reg_64_bit: +#endif + mrs x8, par_el1 + bl str_in_crash_buf_print +2: + adr x6, non_el3_sys_regs_3 + mrs x8, mpidr_el1 + mrs x9, afsr0_el1 + mrs x10, afsr1_el1 + mrs x11, contextidr_el1 + mrs x12, vbar_el1 + mrs x13, cntp_ctl_el0 + mrs x14, cntp_cval_el0 + mrs x15, cntv_ctl_el0 + bl str_in_crash_buf_print + mrs x8, cntv_cval_el0 + mrs x9, cntkctl_el1 + mrs x10, sp_el0 + mrs x11, isr_el1 bl str_in_crash_buf_print #if CTX_INCLUDE_AARCH32_REGS diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h index 4d26153dd..dfa2f9790 100644 --- a/include/arch/aarch64/arch.h +++ b/include/arch/aarch64/arch.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -322,15 +322,15 @@ #define MOPS_IMPLEMENTED ULL(0x1) -/* ID_AA64PFR2_EL1 definitions */ -#define ID_AA64PFR2_EL1 S3_0_C0_C4_2 - #define ID_AA64ISAR2_GPA3_SHIFT U(8) #define ID_AA64ISAR2_GPA3_MASK ULL(0xf) #define ID_AA64ISAR2_APA3_SHIFT U(12) #define ID_AA64ISAR2_APA3_MASK ULL(0xf) +#define ID_AA64ISAR2_SYSREG128_SHIFT U(32) +#define ID_AA64ISAR2_SYSREG128_MASK ULL(0xf) + /* ID_AA64MMFR0_EL1 definitions */ #define ID_AA64MMFR0_EL1_PARANGE_SHIFT U(0) #define ID_AA64MMFR0_EL1_PARANGE_MASK ULL(0xf) @@ -460,6 +460,8 @@ #define RNG_TRAP_IMPLEMENTED ULL(0x1) /* ID_AA64PFR2_EL1 definitions */ +#define ID_AA64PFR2_EL1 S3_0_C0_C4_2 + #define ID_AA64PFR2_EL1_MTEPERM_SHIFT U(0) #define ID_AA64PFR2_EL1_MTEPERM_MASK ULL(0xf) diff --git a/include/arch/aarch64/asm_macros.S b/include/arch/aarch64/asm_macros.S index 197ea0600..ff0127819 100644 --- a/include/arch/aarch64/asm_macros.S +++ b/include/arch/aarch64/asm_macros.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -326,4 +326,18 @@ adrp \dst, \sym add \dst, \dst, :lo12:\sym .endm + + /* + * is_feat_sysreg128_present_asm - Set flags and reg if FEAT_SYSREG128 + * is enabled at runtime. + * + * Arguments: + * reg: Register for temporary use. + * + * Clobbers: reg + */ + .macro is_feat_sysreg128_present_asm reg:req + mrs \reg, ID_AA64ISAR2_EL1 + ands \reg, \reg, #(ID_AA64ISAR2_SYSREG128_MASK << ID_AA64ISAR2_SYSREG128_SHIFT) + .endm #endif /* ASM_MACROS_S */ diff --git a/lib/extensions/sysreg128/sysreg128.S b/lib/extensions/sysreg128/sysreg128.S index 08cff2fb2..c8f304e95 100644 --- a/lib/extensions/sysreg128/sysreg128.S +++ b/lib/extensions/sysreg128/sysreg128.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Arm Limited. All rights reserved. + * Copyright (c) 2025, Arm Limited. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -37,15 +37,14 @@ */ .macro _mrrs regins:req #if ENABLE_FEAT_D128 == 2 - mrs x0, ID_AA64MMFR3_EL1 - tst x0, #(ID_AA64MMFR3_EL1_D128_MASK << ID_AA64MMFR3_EL1_D128_SHIFT) + is_feat_sysreg128_present_asm x0 bne 1f - /* If FEAT_D128 is not implemented then use mrs */ - .inst 0xD5300000 | (\regins) + /* If FEAT_SYSREG128 is not implemented then use mrs */ + .inst 0xD5300000 | (\regins) /* mrs x0, \regins */ ret #endif 1: - .inst 0xD5700000 | (\regins) + .inst 0xD5700000 | (\regins) /* mrrs x0, x1, \regins */ ret .endm @@ -59,18 +58,16 @@ * Clobbers: x0,x1,x2 */ .macro _msrr regins:req - /* If FEAT_D128 is not implemented use msr, dont tamper - * x0, x1 as they maybe used for mrrs */ #if ENABLE_FEAT_D128 == 2 - mrs x2, ID_AA64MMFR3_EL1 - tst x2, #(ID_AA64MMFR3_EL1_D128_MASK << ID_AA64MMFR3_EL1_D128_SHIFT) + /* Don't tamper x0 and x1 as they may be used for msrr */ + is_feat_sysreg128_present_asm x2 bne 1f - /* If FEAT_D128 is not implemented then use msr */ - .inst 0xD5100000 | (\regins) + /* If FEAT_SYSREG128 is not implemented then use msr */ + .inst 0xD5100000 | (\regins) /* msr \regins, x0 */ ret #endif 1: - .inst 0xD5500000 | (\regins) + .inst 0xD5500000 | (\regins) /* msrr \regins, x0, x1 */ ret .endm