diff --git a/ArmPkg/Include/Library/ArmSmcLib.h b/ArmPkg/Include/Library/ArmSmcLib.h index ff946f2dea..168e3bb426 100644 --- a/ArmPkg/Include/Library/ArmSmcLib.h +++ b/ArmPkg/Include/Library/ArmSmcLib.h @@ -1,6 +1,6 @@ /** @file * -* Copyright (c) 2012, ARM Limited. All rights reserved. +* Copyright (c) 2012-2014, ARM Limited. All rights reserved. * * This program and the accompanying materials * are licensed and made available under the terms and conditions of the BSD License @@ -15,30 +15,32 @@ #ifndef __ARM_SMC_LIB__ #define __ARM_SMC_LIB__ +/** + * The size of the SMC arguments are different between AArch64 and AArch32. + * The native size is used for the arguments. + */ +typedef struct { + UINTN Arg0; + UINTN Arg1; + UINTN Arg2; + UINTN Arg3; + UINTN Arg4; + UINTN Arg5; + UINTN Arg6; + UINTN Arg7; +} ARM_SMC_ARGS; + +/** + Trigger an SMC call + + SMC calls can take up to 7 arguments and return up to 4 return values. + Therefore, the 4 first fields in the ARM_SMC_ARGS structure are used + for both input and output values. + +**/ VOID ArmCallSmc ( - IN OUT UINTN *Rx - ); - -VOID -ArmCallSmcArg1 ( - IN OUT UINTN *Rx, - IN OUT UINTN *Arg1 - ); - -VOID -ArmCallSmcArg2 ( - IN OUT UINTN *Rx, - IN OUT UINTN *Arg1, - IN OUT UINTN *Arg2 - ); - -VOID -ArmCallSmcArg3 ( - IN OUT UINTN *Rx, - IN OUT UINTN *Arg1, - IN OUT UINTN *Arg2, - IN OUT UINTN *Arg3 + IN OUT ARM_SMC_ARGS *Args ); #endif diff --git a/ArmPkg/Library/ArmSmcLib/AArch64/ArmSmc.S b/ArmPkg/Library/ArmSmcLib/AArch64/ArmSmc.S index 579a73e96c..f73c98cfc3 100644 --- a/ArmPkg/Library/ArmSmcLib/AArch64/ArmSmc.S +++ b/ArmPkg/Library/ArmSmcLib/AArch64/ArmSmc.S @@ -1,5 +1,5 @@ // -// Copyright (c) 2012-2013, ARM Limited. All rights reserved. +// Copyright (c) 2012-2014, ARM Limited. All rights reserved. // // This program and the accompanying materials // are licensed and made available under the terms and conditions of the BSD License @@ -15,64 +15,27 @@ .align 3 GCC_ASM_EXPORT(ArmCallSmc) -GCC_ASM_EXPORT(ArmCallSmcArg1) -GCC_ASM_EXPORT(ArmCallSmcArg2) -GCC_ASM_EXPORT(ArmCallSmcArg3) ASM_PFX(ArmCallSmc): - str x1, [sp, #-0x10]! - mov x1, x0 - ldr x0,[x1] - smc #0 - str x0,[x1] - ldr x1, [sp], #0x10 - ret + // Push x0 on the stack + str x0, [sp, #-8]! -ASM_PFX(ArmCallSmcArg1): - stp x2, x3, [sp, #-0x10]! - mov x2, x0 - mov x3, x1 - ldr x0,[x2] - ldr x1,[x3] - smc #0 - str x0,[x2] - str x1,[x3] - ldp x2, x3, [sp], #0x10 - ret + // Load the SMC arguments values into the appropriate registers + ldp x6, x7, [x0, #48] + ldp x4, x5, [x0, #32] + ldp x2, x3, [x0, #16] + ldp x0, x1, [x0, #0] -ASM_PFX(ArmCallSmcArg2): - stp x3, x4, [sp, #-0x10]! - str x5, [sp, #-8]! - mov x3, x0 - mov x4, x1 - mov x5, x2 - ldr x0,[x3] - ldr x1,[x4] - ldr x2,[x5] smc #0 - str x0,[x3] - str x1,[x4] - str x2,[x5] - ldr x5, [sp], #8 - ldp x3, x4, [sp], #0x10 - ret -ASM_PFX(ArmCallSmcArg3): - stp x4, x5, [sp, #-0x10]! - stp x6, x7, [sp, #-0x10]! - mov x4, x0 - mov x5, x1 - mov x6, x2 - mov x7, x3 - ldr x0,[x4] - ldr x1,[x5] - ldr x2,[x6] - ldr x3,[x7] - smc #0 - str x0,[x4] - str x1,[x5] - str x2,[x6] - str x3,[x7] - ldp x4, x5, [sp], #0x10 - ldp x6, x7, [sp], #0x10 + // Pop the ARM_SMC_ARGS structure address from the stack into x9 + ldr x9, [sp], #8 + + // Store the SMC returned values into the appropriate registers + // A SMC call can return up to 4 values - we do not need to store back x4-x7. + stp x2, x3, [x9, #16] + stp x0, x1, [x9, #0] + + mov x0, x9 + ret diff --git a/ArmPkg/Library/ArmSmcLib/Arm/ArmSmc.S b/ArmPkg/Library/ArmSmcLib/Arm/ArmSmc.S index c9c0740feb..260fb10fe8 100644 --- a/ArmPkg/Library/ArmSmcLib/Arm/ArmSmc.S +++ b/ArmPkg/Library/ArmSmcLib/Arm/ArmSmc.S @@ -1,5 +1,5 @@ // -// Copyright (c) 2012, ARM Limited. All rights reserved. +// Copyright (c) 2012-2014, ARM Limited. All rights reserved. // // This program and the accompanying materials // are licensed and made available under the terms and conditions of the BSD License @@ -16,60 +16,37 @@ .arch_extension sec GCC_ASM_EXPORT(ArmCallSmc) -GCC_ASM_EXPORT(ArmCallSmcArg1) -GCC_ASM_EXPORT(ArmCallSmcArg2) -GCC_ASM_EXPORT(ArmCallSmcArg3) ASM_PFX(ArmCallSmc): - push {r1} - mov r1, r0 - ldr r0,[r1] - smc #0 - str r0,[r1] - pop {r1} - bx lr + push {r4-r8} + // r0 will be popped just after the SMC call + push {r0} -ASM_PFX(ArmCallSmcArg1): - push {r2-r3} - mov r2, r0 - mov r3, r1 - ldr r0,[r2] - ldr r1,[r3] - smc #0 - str r0,[r2] - str r1,[r3] - pop {r2-r3} - bx lr + // Load the SMC arguments values into the appropriate registers + ldr r7, [r0, #28] + ldr r6, [r0, #24] + ldr r5, [r0, #20] + ldr r4, [r0, #16] + ldr r3, [r0, #12] + ldr r2, [r0, #8] + ldr r1, [r0, #4] + ldr r0, [r0, #0] -ASM_PFX(ArmCallSmcArg2): - push {r3-r5} - mov r3, r0 - mov r4, r1 - mov r5, r2 - ldr r0,[r3] - ldr r1,[r4] - ldr r2,[r5] smc #0 - str r0,[r3] - str r1,[r4] - str r2,[r5] - pop {r3-r5} - bx lr -ASM_PFX(ArmCallSmcArg3): - push {r4-r7} - mov r4, r0 - mov r5, r1 - mov r6, r2 - mov r7, r3 - ldr r0,[r4] - ldr r1,[r5] - ldr r2,[r6] - ldr r3,[r7] - smc #0 - str r0,[r4] - str r1,[r5] - str r2,[r6] - str r3,[r7] - pop {r4-r7} + // Pop the ARM_SMC_ARGS structure address from the stack into r8 + pop {r8} + + // Load the SMC returned values into the appropriate registers + // A SMC call can return up to 4 values - we do not need to store back r4-r7. + str r3, [r8, #12] + str r2, [r8, #8] + str r1, [r8, #4] + str r0, [r8, #0] + + mov r0, r8 + + // Restore the registers r4-r8 + pop {r4-r8} + bx lr diff --git a/ArmPkg/Library/ArmSmcLib/Arm/ArmSmc.asm b/ArmPkg/Library/ArmSmcLib/Arm/ArmSmc.asm index f46bd7ecd4..ad55ae7752 100644 --- a/ArmPkg/Library/ArmSmcLib/Arm/ArmSmc.asm +++ b/ArmPkg/Library/ArmSmcLib/Arm/ArmSmc.asm @@ -1,5 +1,5 @@ // -// Copyright (c) 2012, ARM Limited. All rights reserved. +// Copyright (c) 2012-2014, ARM Limited. All rights reserved. // // This program and the accompanying materials // are licensed and made available under the terms and conditions of the BSD License @@ -12,64 +12,41 @@ // EXPORT ArmCallSmc - EXPORT ArmCallSmcArg1 - EXPORT ArmCallSmcArg2 - EXPORT ArmCallSmcArg3 AREA ArmSmc, CODE, READONLY ArmCallSmc - push {r1} - mov r1, r0 - ldr r0,[r1] - smc #0 - str r0,[r1] - pop {r1} - bx lr + push {r4-r8} + // r0 will be popped just after the SMC call + pop {r0} -ArmCallSmcArg1 - push {r2-r3} - mov r2, r0 - mov r3, r1 - ldr r0,[r2] - ldr r1,[r3] - smc #0 - str r0,[r2] - str r1,[r3] - pop {r2-r3} - bx lr + // Load the SMC arguments values into the appropriate registers + ldr r7, [r0, #28] + ldr r6, [r0, #24] + ldr r5, [r0, #20] + ldr r4, [r0, #16] + ldr r3, [r0, #12] + ldr r2, [r0, #8] + ldr r1, [r0, #4] + ldr r0, [r0, #0] -ArmCallSmcArg2 - push {r3-r5} - mov r3, r0 - mov r4, r1 - mov r5, r2 - ldr r0,[r3] - ldr r1,[r4] - ldr r2,[r5] smc #0 - str r0,[r3] - str r1,[r4] - str r2,[r5] - pop {r3-r5} - bx lr -ArmCallSmcArg3 - push {r4-r7} - mov r4, r0 - mov r5, r1 - mov r6, r2 - mov r7, r3 - ldr r0,[r4] - ldr r1,[r5] - ldr r2,[r6] - ldr r3,[r7] - smc #0 - str r0,[r4] - str r1,[r5] - str r2,[r6] - str r3,[r7] - pop {r4-r7} + // Pop the ARM_SMC_ARGS structure address from the stack into r8 + pop {r8} + + // Load the SMC returned values into the appropriate registers + // A SMC call can return up to 4 values - we do not need to store back r4-r7. + str r3, [r8, #12] + str r2, [r8, #8] + str r1, [r8, #4] + str r0, [r8, #0] + + mov r0, r8 + + // Restore the registers r4-r8 + pop {r4-r8} + bx lr END diff --git a/ArmPkg/Library/ArmSmcLibNull/AArch64/ArmSmcNull.S b/ArmPkg/Library/ArmSmcLibNull/AArch64/ArmSmcNull.S index ec6e067ac3..a6ef0e04da 100644 --- a/ArmPkg/Library/ArmSmcLibNull/AArch64/ArmSmcNull.S +++ b/ArmPkg/Library/ArmSmcLibNull/AArch64/ArmSmcNull.S @@ -1,5 +1,5 @@ // -// Copyright (c) 2012-2013, ARM Limited. All rights reserved. +// Copyright (c) 2012-2014, ARM Limited. All rights reserved. // // This program and the accompanying materials // are licensed and made available under the terms and conditions of the BSD License @@ -15,18 +15,6 @@ .align 3 GCC_ASM_EXPORT(ArmCallSmc) -GCC_ASM_EXPORT(ArmCallSmcArg1) -GCC_ASM_EXPORT(ArmCallSmcArg2) -GCC_ASM_EXPORT(ArmCallSmcArg3) ASM_PFX(ArmCallSmc): ret - -ASM_PFX(ArmCallSmcArg1): - ret - -ASM_PFX(ArmCallSmcArg2): - ret - -ASM_PFX(ArmCallSmcArg3): - ret diff --git a/ArmPkg/Library/ArmSmcLibNull/Arm/ArmSmcNull.S b/ArmPkg/Library/ArmSmcLibNull/Arm/ArmSmcNull.S index 4896dd0c9b..9eaefd30cf 100644 --- a/ArmPkg/Library/ArmSmcLibNull/Arm/ArmSmcNull.S +++ b/ArmPkg/Library/ArmSmcLibNull/Arm/ArmSmcNull.S @@ -1,5 +1,5 @@ // -// Copyright (c) 2012-2013, ARM Limited. All rights reserved. +// Copyright (c) 2012-2014, ARM Limited. All rights reserved. // // This program and the accompanying materials // are licensed and made available under the terms and conditions of the BSD License @@ -15,19 +15,6 @@ .align 3 GCC_ASM_EXPORT(ArmCallSmc) -GCC_ASM_EXPORT(ArmCallSmcArg1) -GCC_ASM_EXPORT(ArmCallSmcArg2) -GCC_ASM_EXPORT(ArmCallSmcArg3) ASM_PFX(ArmCallSmc): bx lr - -// Arg1 in R1 -ASM_PFX(ArmCallSmcArg1): - bx lr - -ASM_PFX(ArmCallSmcArg2): - bx lr - -ASM_PFX(ArmCallSmcArg3): - bx lr diff --git a/ArmPkg/Library/ArmSmcLibNull/Arm/ArmSmcNull.asm b/ArmPkg/Library/ArmSmcLibNull/Arm/ArmSmcNull.asm index 24c20752e3..3d3f554554 100644 --- a/ArmPkg/Library/ArmSmcLibNull/Arm/ArmSmcNull.asm +++ b/ArmPkg/Library/ArmSmcLibNull/Arm/ArmSmcNull.asm @@ -1,5 +1,5 @@ // -// Copyright (c) 2012-2013, ARM Limited. All rights reserved. +// Copyright (c) 2012-2014, ARM Limited. All rights reserved. // // This program and the accompanying materials // are licensed and made available under the terms and conditions of the BSD License @@ -12,23 +12,10 @@ // EXPORT ArmCallSmc - EXPORT ArmCallSmcArg1 - EXPORT ArmCallSmcArg2 - EXPORT ArmCallSmcArg3 AREA ArmSmc, CODE, READONLY ArmCallSmc bx lr -// Arg1 in R1 -ArmCallSmcArg1 - bx lr - -ArmCallSmcArg2 - bx lr - -ArmCallSmcArg3 - bx lr - END