blob: d71a2009824a272cda4a7545b0116aad7b34718b [file] [log] [blame]
/*
* Copyright (c) 2013-2016 Marvell International Ltd. and its affiliates.
* All rights reserved.
*
* This software file (the "File") is owned and distributed by Marvell
* International Ltd. and/or its affiliates ("Marvell") under the following
* licensing terms.
*
* Marvell Commercial License Option
* ------------------------------------
* If you received this File from Marvell and you have entered into a
* commercial license agreement (a "Commercial License") with Marvell, the
* File is licensed to you under the terms of the applicable Commercial
* License.
*
* Marvell GPL License Option
* ------------------------------------
* If you received this File from Marvell, you may opt to use, redistribute
* and/or modify this File in accordance with the terms and conditions of the
* General Public License Version 2, June 1991 (the "GPL License"), a copy of
* which is available along with the File in the license.txt file or by writing
* to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
* THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
* WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE
* EXPRESSLY DISCLAIMED. The GPL License provides additional details about this
* warranty disclaimer.
*/
.text
/** SMC Calling Conversion - Argument passing
* Document number: ARM DEN 0028A
*
* http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
*
* [SMC32 Argument passing]
*
* When the SMC32 convention is used, the SMC intructions take up to seven
* 32-bit arguments in register and can return up to four 32-bit values in
* registers.
*
* When an SMC32 call is made from AArch32:
* o Arguments are passed in register R0-R6
* o Results are returned in R0-R3
* o Registers R4-R14 are callee-saved and must be preserved over the SMC call
*
* When an SMC32 call is made from AArch64:
* o Arguments are passed in register X0-X6
* o Results are returned in X0-X3
* o Registers X18-X30 and stack pointers SP_EL0 and SP_ELx are callee-saved and
* must be preserved over the SMC call
*
* [SMC64 Argument passing]
*
* When the SMC64 convention is used, the SMC instructions take up to seven 64-bit
* arguments in registers and can return up to four 64-bit values in register
*
* When an SMC64 call is made from AArch64:
* o Arguments are passed in register X0-X6
* o Results are returned in X0-X3
* o Registers X18-X30 and stack pointers SP_EL0 and SP_ELx are callee-saved and
* must ber preserved over the SMC call
*
* Then calling convention cannot be used by code executing AArch32 state
*/
/** SMC call command with 2 parameters
*
* unsigned long __smc_cmd2(unsigned long func_id,
* unsigned long param0,
* unsigned long param1,
* unsigned long result[2])
*
* @param func_id function ID in x0
* @param param0 parameters 0 in x1
* @param param1 parameters 1 in x2
* @param result pointer to returned results (x1-x2) in x3 if not NULL
*
* @retval 0xffffffff invalidate function ID
* @retval others status
*
*/
.globl __smc_cmd2
__smc_cmd2:
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* Save in the stack, stack pointer MUST be quadword aligned
* that is it must be aligned to 16 bytes. Misalignment
* generates a Stack Alighment fault
* ----------------------------------------------------------
*/
stp x29, x30, [sp, #-32]!
mov x29, sp
/* ----------------------------------------------------------
* x0 = function ID, x1 = param0, x2 = param1
*
* preserve x19 on the stack and x3 in x19
* x3 contains the pointer to returned value
* x19 as a temporary register
* ----------------------------------------------------------
*/
str x19, [sp, #16]
mov x19, x3
/* ----------------------------------------------------------
* make smc call now
* ----------------------------------------------------------
*/
smc #0
/* ---------------------------------------------------------
* x0-x3 contains the returned value
*
* If the pointer is not NULL saved x1-x2 to result[2]
* ---------------------------------------------------------
*/
cbz x19, 1f
stp x1, x2, [x19]
1:
/* ----------------------------------------------------------
* restore x19 from stack
* ----------------------------------------------------------
*/
ldr x19, [sp, #16]
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* restore link address register & frame pointer register
* ----------------------------------------------------------
*/
ldp x29, x30, [sp], #32
/* ---------------------------------------------------------
* back to caller
* ---------------------------------------------------------
*/
ret
/** SMC call command with 3 parameters.
*
* unsigned long __smc_cmd3(unsigned long func_id,
* unsigned long param0,
* unsigned long param1,
* unsigned long param2,
* unsigned long result[3]);
*
* unsigned long __smc3(unsigned long func_id,
* unsigned long param0,
* unsigned long param1,
* unsigned long param2,
* unsigned long result[3]);
*
* @param func_id function ID in x0
* @param param0 parameter 0 in x1
* @param param1 parameter 1 in x2
* @param param2 parameter 2 in x3
* @param result pointer to return results (x1-x3) in x4 if not NULL
*
* @retval 0xffffffff invalidate Function ID.
* @retval others status
*/
.globl __smc_cmd3
__smc_cmd3:
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* Save in the stack, stack pointer MUST be quadword aligned
* that is it must be aligned to 16 bytes. Misalignment
* generates a Stack Alighment fault
* ----------------------------------------------------------
*/
stp x29, x30, [sp, #-32]!
mov x29, sp
/* ----------------------------------------------------------
* x0 = function ID, x1 = param0, x2 = param1, x3 = param2
*
* preserve x19 on the stack and x4 in x19
* x4 contains the pointer to returned value
* x19 as a temporary register
* ----------------------------------------------------------
*/
str x19, [sp, #16]
mov x19, x4
/* ----------------------------------------------------------
* make smc call now
* ----------------------------------------------------------
*/
smc #0
/* ---------------------------------------------------------
* x0-x3 contains the returned value
*
* If the pointer is not NULL saved x1-x3 to result[3]
* ---------------------------------------------------------
*/
cbz x19, 1f
stp x1, x2, [x19]
str x3, [x19, #16]
1:
/* ----------------------------------------------------------
* restore x19 from stack
* ----------------------------------------------------------
*/
ldr x19, [sp, #16]
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* restore link address register & frame pointer register
* ----------------------------------------------------------
*/
ldp x29, x30, [sp], #32
/* ---------------------------------------------------------
* back to caller
* ---------------------------------------------------------
*/
ret
/** SMC call without results.
*
* unsigned long __smc(unsigned long func_id, ...);
*
* @note it can be used as bellow:
* status = smc_nores(func_id);
* status = smc_nores(func_id, param0);
* status = smc_nores(func_id, param0, param1);
* status = smc_nores(func_id, param0, param1, param2);
* status = smc_nores(func_id, param0, param1, param2, param3);
*
* @param func_id function ID in x0
* @param param0 parameter 0 in x1
* @param param1 parameter 1 in x2
* @param param2 parameter 2 in x3
* @param param3 parameter 3 in x4
*
* @retval 0xffffffff invalidate Function ID.
* @retval others status
*/
.globl __smc
__smc:
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* Save in the stack, stack pointer MUST be quadword aligned
* that is it must be aligned to 16 bytes. Misalignment
* generates a Stack Alighment fault
* ----------------------------------------------------------
*/
stp x29, x30, [sp, #-16]!
mov x29, sp
/* ----------------------------------------------------------
* make smc call now
* ----------------------------------------------------------
*/
smc #0
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* restore link address register & frame pointer register
* ----------------------------------------------------------
*/
ldp x29, x30, [sp], #16
/* ---------------------------------------------------------
* back to caller
* ---------------------------------------------------------
*/
ret
/** SMC call with 4 parameters without results.
*
* unsigned long __smc4(unsigned long func_id,
* unsigned long param0,
* unsigned long param1,
* unsigned long param2,
* unsigned long param3)
*
* @param func_id function ID in x0
* @param param0 parameter 0 in x1
* @param param1 parameter 1 in x2
* @param param2 parameter 2 in x3
* @param param3 parameter 3 in x4
*
* @retval 0xffffffff invalidate Function ID.
* @retval others status
*/
.globl __smc4
__smc4:
b __smc
/** SMC call command with 3 parameters.
*
* unsigned long __smc3(unsigned long func_id,
* unsigned long param0,
* unsigned long param1,
* unsigned long param2,
* unsigned long result[4]);
*
* @param func_id function ID in x0
* @param param0 parameter 0 in x1
* @param param1 parameter 1 in x2
* @param param2 parameter 2 in x3
* @param result pointer to return results (x0-x3) in x4 if not NULL
*
* @retval 0xffffffff invalidate Function ID.
* @retval others status
*/
.globl __smc3
__smc3:
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* Save in the stack, stack pointer MUST be quadword aligned
* that is it must be aligned to 16 bytes. Misalignment
* generates a Stack Alighment fault
* ----------------------------------------------------------
*/
stp x29, x30, [sp, #-32]!
mov x29, sp
/* ----------------------------------------------------------
* x0 = function ID, x1 = param0, x2 = param1, x3 = param2
*
* preserve x4 and x19 on the stack and x4 in x19
* x4 contains the pointer to returned value
* x19 as a temporary register
* ----------------------------------------------------------
*/
str x19, [sp, #16]
mov x19, x4
/* ----------------------------------------------------------
* make smc call now
* ----------------------------------------------------------
*/
smc #0
/* ---------------------------------------------------------
* x0-x3 contains the returned value
*
* If the pointer is not NULL saved x0-x3 to result[4]
* ---------------------------------------------------------
*/
cbz x19, 1f
stp x0, x1, [x19]
stp x2, x3, [x19, #16]
1:
/* ----------------------------------------------------------
* restore x19 from stack
* ----------------------------------------------------------
*/
ldr x19, [sp, #16]
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* restore link address register & frame pointer register
* ----------------------------------------------------------
*/
ldp x29, x30, [sp], #32
/* ---------------------------------------------------------
* back to caller
* ---------------------------------------------------------
*/
ret
/** SMC call with 6 parameters.
*
* unsigned long __smc6(unsigned long func_id,
* const unsigned long param[6],
* unsigned long result[4]);
*
* @param func_id function ID in x0
* @param param buffer to store 6 parmeters in r1
* @param result buffer to return results (x0-x3) in r2 if not NULL
* result[0] is returned by function too
*
* @retval 0xffffffff invalidate Function ID.
* @retval others status
*/
.globl __smc6
__smc6:
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* Save in the stack, stack pointer MUST be quadword aligned
* that is it must be aligned to 16 bytes. Misalignment
* generates a Stack Alighment fault
* ----------------------------------------------------------
*/
stp x29, x30, [sp, #-32]!
mov x29, sp
/* ----------------------------------------------------------
* x0 = function ID
* x1 = pointer to 6 parameters (x1-x6)
* x2 = pointer to return results (x0-x3)
*
* preserve x19 on the stack and x2 in x19
* x2 contains the pointer to the returned value
* x19 as a temporary register
* ----------------------------------------------------------
*/
str x19, [sp, #16]
mov x19, x2
/* ----------------------------------------------------------
* Load 6 parameters into r1-r6, will panic if r1=NULL
*
* x9 = ip0, first intra-procedure-call scratch register
* ----------------------------------------------------------
*/
mov x9, x1
ldp x1, x2, [x9]
ldp x3, x4, [x9, #16]
ldp x5, x6, [x9, #32]
/* ----------------------------------------------------------
* make smc call now
* ----------------------------------------------------------
*/
smc #0
/* ---------------------------------------------------------
* x0-x3 contains the returned value
*
* If the pointer is not NULL saved x1-x3 to result[4]
* ---------------------------------------------------------
*/
cbz x19, 1f
stp x0, x1, [x19]
stp x2, x3, [x19, #16]
1:
/* ----------------------------------------------------------
* restore x19 from stack
* ----------------------------------------------------------
*/
ldr x19, [sp, #16]
/* ----------------------------------------------------------
* x30 = link address, x29 = frame pointer
*
* restore link address register & frame pointer register
* ----------------------------------------------------------
*/
ldp x29, x30, [sp], #32
/* ---------------------------------------------------------
* back to caller
* ---------------------------------------------------------
*/
ret