arm-trusted-firmware/include/common/asm_macros.S

234 lines
6.1 KiB
ArmAsm
Raw Normal View History

2013-10-25 09:08:21 +01:00
/*
* Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved.
2013-10-25 09:08:21 +01:00
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __ASM_MACROS_S__
#define __ASM_MACROS_S__
2013-10-25 09:08:21 +01:00
#include <arch.h>
2013-10-25 09:08:21 +01:00
.macro func_prologue
stp x29, x30, [sp, #-0x10]!
mov x29,sp
.endm
.macro func_epilogue
ldp x29, x30, [sp], #0x10
.endm
.macro dcache_line_size reg, tmp
mrs \tmp, ctr_el0
2013-10-25 09:08:21 +01:00
ubfx \tmp, \tmp, #16, #4
mov \reg, #4
lsl \reg, \reg, \tmp
2013-10-25 09:08:21 +01:00
.endm
.macro icache_line_size reg, tmp
mrs \tmp, ctr_el0
and \tmp, \tmp, #0xf
mov \reg, #4
lsl \reg, \reg, \tmp
2013-10-25 09:08:21 +01:00
.endm
.macro smc_check label
mrs x0, esr_el3
2013-10-25 09:08:21 +01:00
ubfx x0, x0, #ESR_EC_SHIFT, #ESR_EC_LENGTH
cmp x0, #EC_AARCH64_SMC
b.ne $label
.endm
/*
* Declare the exception vector table, enforcing it is aligned on a
* 2KB boundary, as required by the ARMv8 architecture.
*/
.macro vector_base label
.section .vectors, "ax"
.align 11
\label:
.endm
/*
* Create an entry in the exception vector table, enforcing it is
* aligned on a 128-byte boundary, as required by the ARMv8 architecture.
*/
.macro vector_entry label
.section .vectors, "ax"
.align 7
\label:
.endm
2013-10-25 09:08:21 +01:00
/*
* This macro verifies that the given vector doesn't exceed the
* architectural limit of 32 instructions. This is meant to be placed
* immediately after the last instruction in the vector. It takes the
* vector entry as the parameter
*/
.macro check_vector_size since
.if (. - \since) > (32 * 4)
.error "Vector exceeds 32 instructions"
.endif
.endm
/*
* This macro is used to create a function label and place the
* code into a separate text section based on the function name
* to enable elimination of unused code during linking
*/
.macro func _name
.section .text.\_name, "ax"
.type \_name, %function
.func \_name
\_name:
.endm
/*
* This macro is used to mark the end of a function.
*/
.macro endfunc _name
.endfunc
.size \_name, . - \_name
.endm
/*
* Theses macros are used to create function labels for deprecated
* APIs. If ERROR_DEPRECATED is non zero, the callers of these APIs
* will fail to link and cause build failure.
*/
#if ERROR_DEPRECATED
.macro func_deprecated _name
func deprecated\_name
.endm
.macro endfunc_deprecated _name
endfunc deprecated\_name
.endm
#else
.macro func_deprecated _name
func \_name
.endm
.macro endfunc_deprecated _name
endfunc \_name
.endm
#endif
/*
* This macro declares an array of 1 or more stacks, properly
* aligned and in the requested section
*/
#define STACK_ALIGN 6
.macro declare_stack _name, _section, _size, _count
.if ((\_size & ((1 << STACK_ALIGN) - 1)) <> 0)
.error "Stack size not correctly aligned"
.endif
.section \_section, "aw", %nobits
.align STACK_ALIGN
\_name:
.space ((\_count) * (\_size)), 0
.endm
#if ENABLE_PLAT_COMPAT
/*
* This macro calculates the base address of an MP stack using the
* platform_get_core_pos() index, the name of the stack storage and
* the size of each stack
* In: X0 = MPIDR of CPU whose stack is wanted
* Out: X0 = physical address of stack base
* Clobber: X30, X1, X2
*/
.macro get_mp_stack _name, _size
bl platform_get_core_pos
ldr x2, =(\_name + \_size)
mov x1, #\_size
madd x0, x0, x1, x2
.endm
#endif
PSCI: Introduce new platform and CM helper APIs This patch introduces new platform APIs and context management helper APIs to support the new topology framework based on linear core position. This framework will be introduced in the follwoing patch and it removes the assumption that the MPIDR based affinity levels map directly to levels in a power domain tree. The new platforms APIs and context management helpers based on core position are as described below: * plat_my_core_pos() and plat_core_pos_by_mpidr() These 2 new mandatory platform APIs are meant to replace the existing 'platform_get_core_pos()' API. The 'plat_my_core_pos()' API returns the linear index of the calling core and 'plat_core_pos_by_mpidr()' returns the linear index of a core specified by its MPIDR. The latter API will also validate the MPIDR passed as an argument and will return an error code (-1) if an invalid MPIDR is passed as the argument. This enables the caller to safely convert an MPIDR of another core to its linear index without querying the PSCI topology tree e.g. during a call to PSCI CPU_ON. Since the 'plat_core_pos_by_mpidr()' API verifies an MPIDR, which is always platform specific, it is no longer possible to maintain a default implementation of this API. Also it might not be possible for a platform port to verify an MPIDR before the C runtime has been setup or the topology has been initialized. This would prevent 'plat_core_pos_by_mpidr()' from being callable prior to topology setup. As a result, the generic Trusted Firmware code does not call this API before the topology setup has been done. The 'plat_my_core_pos' API should be able to run without a C runtime. Since this API needs to return a core position which is equal to the one returned by 'plat_core_pos_by_mpidr()' API for the corresponding MPIDR, this too cannot have default implementation and is a mandatory API for platform ports. These APIs will be implemented by the ARM reference platform ports later in the patch stack. * plat_get_my_stack() and plat_set_my_stack() These APIs are the stack management APIs which set/return stack addresses appropriate for the calling core. These replace the 'platform_get_stack()' and 'platform_set_stack()' APIs. A default weak MP version and a global UP version of these APIs are provided for the platforms. * Context management helpers based on linear core position A set of new context management(CM) helpers viz cm_get_context_by_index(), cm_set_context_by_index(), cm_init_my_context() and cm_init_context_by_index() are defined which are meant to replace the old helpers which took MPIDR as argument. The old CM helpers are implemented based on the new helpers to allow for code consolidation and will be deprecated once the switch to the new framework is done. Change-Id: I89758632b370c2812973a4b2efdd9b81a41f9b69
2015-04-09 13:40:55 +01:00
/*
* This macro calculates the base address of the current CPU's MP stack
* using the plat_my_core_pos() index, the name of the stack storage
* and the size of each stack
* Out: X0 = physical address of stack base
* Clobber: X30, X1, X2
*/
.macro get_my_mp_stack _name, _size
bl plat_my_core_pos
ldr x2, =(\_name + \_size)
mov x1, #\_size
madd x0, x0, x1, x2
.endm
/*
* This macro calculates the base address of a UP stack using the
* name of the stack storage and the size of the stack
* Out: X0 = physical address of stack base
*/
.macro get_up_stack _name, _size
ldr x0, =(\_name + \_size)
.endm
/*
* Helper macro to generate the best mov/movk combinations according
* the value to be moved. The 16 bits from '_shift' are tested and
* if not zero, they are moved into '_reg' without affecting
* other bits.
*/
.macro _mov_imm16 _reg, _val, _shift
.if (\_val >> \_shift) & 0xffff
.if (\_val & (1 << \_shift - 1))
movk \_reg, (\_val >> \_shift) & 0xffff, LSL \_shift
.else
mov \_reg, \_val & (0xffff << \_shift)
.endif
.endif
.endm
/*
* Helper macro to load arbitrary values into 32 or 64-bit registers
* which generates the best mov/movk combinations. Many base addresses
* are 64KB aligned the macro will eliminate updating bits 15:0 in
* that case
*/
.macro mov_imm _reg, _val
.if (\_val) == 0
mov \_reg, #0
.else
_mov_imm16 \_reg, (\_val), 0
_mov_imm16 \_reg, (\_val), 16
_mov_imm16 \_reg, (\_val), 32
_mov_imm16 \_reg, (\_val), 48
.endif
.endm
#endif /* __ASM_MACROS_S__ */