lib: smc: Add smc8_ret18/hvc8_ret18 am: 09026ddc2d

Original change: https://android-review.googlesource.com/c/trusty/lk/trusty/+/3505621

Change-Id: I46aafe098eafc76b6f4d91a5911e085ee0df7343
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/lib/smc/arch/arm64/smc.S b/lib/smc/arch/arm64/smc.S
index 7749e67..40988eb 100644
--- a/lib/smc/arch/arm64/smc.S
+++ b/lib/smc/arch/arm64/smc.S
@@ -49,6 +49,50 @@
 FUNCTION(hvc8)
     smc8_hvc8 hvc
 
+.macro smc8_hvc8_ret18, instr
+    /*
+     * Save x19 and lr. The SMC calling convention says el3 does not need to
+     * preserve x8 (return value ptr). The aarch64 calling convention (AAPCS64)
+     * says x8 is caller-saved even when used as the return value pointer.
+     */
+    push    x19, lr
+    mov     x19, x8 /* preserve return value pointer in x19  */
+
+    mov     x8,  xzr
+    mov     x9,  xzr
+    mov     x10, xzr
+    mov     x11, xzr
+    mov     x12, xzr
+    mov     x13, xzr
+    mov     x14, xzr
+    mov     x15, xzr
+    mov     x16, xzr
+    mov     x17, xzr
+
+    \instr  #0
+
+    /* Copy 8-register smc return value plus x8-x17 into struct smc_ret18 */
+    stp     x0,  x1,  [x19], #16
+    stp     x2,  x3,  [x19], #16
+    stp     x4,  x5,  [x19], #16
+    stp     x6,  x7,  [x19], #16
+    stp     x8,  x9,  [x19], #16
+    stp     x10, x11, [x19], #16
+    stp     x12, x13, [x19], #16
+    stp     x14, x15, [x19], #16
+    stp     x16, x17, [x19], #16
+
+    pop     x19, lr
+
+    ret
+.endm
+
+FUNCTION(smc8_ret18)
+    smc8_hvc8_ret18 smc
+
+FUNCTION(hvc8_ret18)
+    smc8_hvc8_ret18 hvc
+
 .macro smc18_hvc18, instr
     push x19, lr
     mov  x19, x8
diff --git a/lib/smc/include/lib/smc/smc.h b/lib/smc/include/lib/smc/smc.h
index d73f8f2..d2aa5bc 100644
--- a/lib/smc/include/lib/smc/smc.h
+++ b/lib/smc/include/lib/smc/smc.h
@@ -88,6 +88,30 @@
                      ulong r6,
                      ulong r7);
 
+/*
+ * same as smc8 but returns 18 registers with x8 and above set to zero on entry
+ */
+struct smc_ret18 smc8_ret18(ulong r0,
+                            ulong r1,
+                            ulong r2,
+                            ulong r3,
+                            ulong r4,
+                            ulong r5,
+                            ulong r6,
+                            ulong r7);
+
+/*
+ * same as hvc8 but returns 18 registers with x8 and above set to zero on entry
+ */
+struct smc_ret18 hvc8_ret18(ulong r0,
+                            ulong r1,
+                            ulong r2,
+                            ulong r3,
+                            ulong r4,
+                            ulong r5,
+                            ulong r6,
+                            ulong r7);
+
 struct smc_ret18 smc18(ulong r0,
                        ulong r1,
                        ulong r2,