blob: d4cede99820c350c527a37a07860bfe9d0e95e29 [file] [log] [blame]
/*
* Copyright (c) 2013-2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <asm_macros.S>
.section .text, "ax"
.macro smccc_conduit _conduit
/*
* According to the AAPCS64, x8 is the indirect result location
* register. It contains the address of the memory block that the caller
* has reserved to hold the result, i.e. the smc_ret_values structure
* in our case.
* x8 might be clobbered across the SMC call so save it on the stack.
* Although x8 contains an 8 byte value, we are allocating 16bytes on the stack
* to respect 16byte stack-alignment.
*/
str x8, [sp, #-16]!
/* "Conduit" arguments are already stored in x0-x7 */
\_conduit #0
/* Pop x8 into a caller-saved register */
ldr x9, [sp], #16
/*
* Return values are stored in x0-x7, put them in the 'smc_ret_values'
* return structure
*/
stp x0, x1, [x9, #0]
stp x2, x3, [x9, #16]
stp x4, x5, [x9, #32]
stp x6, x7, [x9, #48]
.endm
.macro smccc_conduit_nox8 _conduit
/*
* Store address pointing at the smc_ret_values structure in the stack
*/
str x1, [sp, #-16]!
/*
* Store arguments in x0..x17. Start from highest registers so address
* pointed by x0 is preserved until it is no longer needed.
*/
ldp x16, x17, [x0, #128]
ldp x14, x15, [x0, #112]
ldp x12, x13, [x0, #96]
ldp x10, x11, [x0, #80]
ldp x8, x9, [x0, #64]
ldp x6, x7, [x0, #48]
ldp x4, x5, [x0, #32]
ldp x2, x3, [x0, #16]
ldp x0, x1, [x0, #0]
/* "Conduit" arguments are already stored in x0..x17 */
\_conduit #0
/*
* Store value received in x0 as x0 will be used to compute addresses
* to store the results.
*/
str x0, [sp, #-16]!
/* Load address of smc_ret_values structure into x0 */
ldr x0, [sp, #16]
/* Store values x1..x17 in the smc_ret_values structure */
stp x16, x17, [x0, #128]
stp x14, x15, [x0, #112]
stp x12, x13, [x0, #96]
stp x10, x11, [x0, #80]
stp x8, x9, [x0, #64]
stp x6, x7, [x0, #48]
stp x4, x5, [x0, #32]
stp x2, x3, [x0, #16]
str x1, [x0, #8]
/*
* Load previously stored value of x0 into x1 and store it in the
* smc_ret_values structure. Return sp to its original position.
*/
ldr x1, [sp], #32
str x1, [x0, #0]
.endm
/* ---------------------------------------------------------------------------
* smc_ret_values asm_tftf_smc64(uint32_t fid,
* u_register_t arg1,
* u_register_t arg2,
* u_register_t arg3,
* u_register_t arg4,
* u_register_t arg5,
* u_register_t arg6,
* u_register_t arg7);
* ---------------------------------------------------------------------------
*/
.globl asm_tftf_smc64
func asm_tftf_smc64
smccc_conduit smc
ret
endfunc asm_tftf_smc64
.globl asm_tftf_smc64_no_retval_x8
/* ---------------------------------------------------------------------------
* void asm_tftf_smc64_no_retval_x8(smc_args *args, smc_ret_values *ret);
* ---------------------------------------------------------------------------
*/
func asm_tftf_smc64_no_retval_x8
smccc_conduit_nox8 smc
ret
endfunc asm_tftf_smc64_no_retval_x8
/* ---------------------------------------------------------------------------
* hvc_ret_values asm_tftf_hvcc64(uint32_t fid,
* u_register_t arg1,
* u_register_t arg2,
* u_register_t arg3,
* u_register_t arg4,
* u_register_t arg5,
* u_register_t arg6,
* u_register_t arg7);
* ---------------------------------------------------------------------------
*/
.globl asm_tftf_hvc64
func asm_tftf_hvc64
smccc_conduit hvc
ret
endfunc asm_tftf_hvc64