diff options
author | Jeenu Viswambharan <jeenu.viswambharan@arm.com> | 2016-11-30 15:21:11 +0000 |
---|---|---|
committer | Jeenu Viswambharan <jeenu.viswambharan@arm.com> | 2016-12-05 14:55:35 +0000 |
commit | a806dad58c4cf752238d7bbffbc9a1ce17f63cea (patch) | |
tree | 9981b72bc40a9169972103ca315549d8a35bb052 /include/common/aarch32 | |
parent | c59428b1502f37c9b2f551613da1b491c4226d10 (diff) |
Define and use no_ret macro where no return is expected
There are many instances in ARM Trusted Firmware where control is
transferred to functions from which return isn't expected. Such jumps
are made using 'bl' instruction to provide the callee with the location
from which it was jumped to. Additionally, debuggers infer the caller by
examining where 'lr' register points to. If a 'bl' of the nature
described above falls at the end of an assembly function, 'lr' will be
left pointing to a location outside of the function range. This misleads
the debugger back trace.
This patch defines a 'no_ret' macro to be used when jumping to functions
from which return isn't expected. The macro ensures to use 'bl'
instruction for the jump, and also, for debug builds, places a 'nop'
instruction immediately thereafter (unless instructed otherwise) so as
to leave 'lr' pointing within the function range.
Change-Id: Ib34c69fc09197cfd57bc06e147cc8252910e01b0
Co-authored-by: Douglas Raillard <douglas.raillard@arm.com>
Signed-off-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
Diffstat (limited to 'include/common/aarch32')
-rw-r--r-- | include/common/aarch32/asm_macros.S | 22 | ||||
-rw-r--r-- | include/common/aarch32/el3_common_macros.S | 2 |
2 files changed, 23 insertions, 1 deletions
diff --git a/include/common/aarch32/asm_macros.S b/include/common/aarch32/asm_macros.S index 5f044991..23122f34 100644 --- a/include/common/aarch32/asm_macros.S +++ b/include/common/aarch32/asm_macros.S @@ -102,4 +102,26 @@ ldr r0, =(\_name + \_size) .endm + /* + * Macro to mark instances where we're jumping to a function and don't + * expect a return. To provide the function being jumped to with + * additional information, we use 'bl' instruction to jump rather than + * 'b'. + * + * Debuggers infer the location of a call from where LR points to, which + * is usually the instruction after 'bl'. If this macro expansion + * happens to be the last location in a function, that'll cause the LR + * to point a location beyond the function, thereby misleading debugger + * back trace. We therefore insert a 'nop' after the function call for + * debug builds, unless 'skip_nop' parameter is non-zero. + */ + .macro no_ret _func:req, skip_nop=0 + bl \_func +#if DEBUG + .ifeq \skip_nop + nop + .endif +#endif + .endm + #endif /* __ASM_MACROS_S__ */ diff --git a/include/common/aarch32/el3_common_macros.S b/include/common/aarch32/el3_common_macros.S index 0018ea4b..228d7216 100644 --- a/include/common/aarch32/el3_common_macros.S +++ b/include/common/aarch32/el3_common_macros.S @@ -212,7 +212,7 @@ /* This is a cold boot on a secondary CPU */ bl plat_secondary_cold_boot_setup /* plat_secondary_cold_boot_setup() is not supposed to return */ - bl plat_panic_handler + no_ret plat_panic_handler do_primary_cold_boot: .endif /* _secondary_cold_boot */ |