| /* |
| * Copyright (C) 2016 The Android Open Source Project |
| * |
| * Permission is hereby granted, free of charge, to any person |
| * obtaining a copy of this software and associated documentation |
| * files (the "Software"), to deal in the Software without |
| * restriction, including without limitation the rights to use, copy, |
| * modify, merge, publish, distribute, sublicense, and/or sell copies |
| * of the Software, and to permit persons to whom the Software is |
| * furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be |
| * included in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| * SOFTWARE. |
| */ |
| |
| #include <trusty/smc.h> |
| |
| #ifndef __asmeq |
| #define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t" |
| #endif |
| |
| #ifdef NS_ARCH_ARM64 |
| #define SMC_ARG0 "x0" |
| #define SMC_ARG1 "x1" |
| #define SMC_ARG2 "x2" |
| #define SMC_ARG3 "x3" |
| #define SMC_ARG4 "x4" |
| #define SMC_ARG5 "x5" |
| #define SMC_ARG6 "x6" |
| #define SMC_ARG7 "x7" |
| #define SMC_ARCH_EXTENSION "" |
| #define SMC_REGISTERS_TRASHED \ |
| "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17" |
| #else |
| #define SMC_ARG0 "r0" |
| #define SMC_ARG1 "r1" |
| #define SMC_ARG2 "r2" |
| #define SMC_ARG3 "r3" |
| #define SMC_ARG4 "r4" |
| #define SMC_ARG5 "r5" |
| #define SMC_ARG6 "r6" |
| #define SMC_ARG7 "r7" |
| #define SMC_ARCH_EXTENSION ".arch_extension sec\n" |
| #define SMC_REGISTERS_TRASHED "ip" |
| #endif |
| |
| /* |
| * Execute SMC call into trusty |
| */ |
| struct smc_ret8 smc8(unsigned long r0, |
| unsigned long r1, |
| unsigned long r2, |
| unsigned long r3, |
| unsigned long r4, |
| unsigned long r5, |
| unsigned long r6, |
| unsigned long r7) { |
| register unsigned long _r0 __asm__(SMC_ARG0) = r0; |
| register unsigned long _r1 __asm__(SMC_ARG1) = r1; |
| register unsigned long _r2 __asm__(SMC_ARG2) = r2; |
| register unsigned long _r3 __asm__(SMC_ARG3) = r3; |
| register unsigned long _r4 __asm__(SMC_ARG4) = r4; |
| register unsigned long _r5 __asm__(SMC_ARG5) = r5; |
| register unsigned long _r6 __asm__(SMC_ARG6) = r6; |
| register unsigned long _r7 __asm__(SMC_ARG7) = r7; |
| |
| /* clang-format off */ |
| __asm__ volatile( |
| __asmeq("%0", SMC_ARG0) |
| __asmeq("%1", SMC_ARG1) |
| __asmeq("%2", SMC_ARG2) |
| __asmeq("%3", SMC_ARG3) |
| __asmeq("%4", SMC_ARG4) |
| __asmeq("%5", SMC_ARG5) |
| __asmeq("%6", SMC_ARG6) |
| __asmeq("%7", SMC_ARG7) |
| __asmeq("%8", SMC_ARG0) |
| __asmeq("%9", SMC_ARG1) |
| __asmeq("%10", SMC_ARG2) |
| __asmeq("%11", SMC_ARG3) |
| __asmeq("%12", SMC_ARG4) |
| __asmeq("%13", SMC_ARG5) |
| __asmeq("%14", SMC_ARG6) |
| __asmeq("%15", SMC_ARG7) |
| SMC_ARCH_EXTENSION |
| "smc #0" /* switch to secure world */ |
| : "=r" (_r0), "=r" (_r1), "=r" (_r2), "=r" (_r3), "=r" (_r4), |
| "=r" (_r5), "=r" (_r6), "=r" (_r7) |
| : "r" (_r0), "r" (_r1), "r" (_r2), "r" (_r3), "r" (_r4), "r" (_r5), |
| "r" (_r6), "r" (_r7) |
| : SMC_REGISTERS_TRASHED); |
| /* clang-format on */ |
| { |
| struct smc_ret8 ret = {_r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7}; |
| return ret; |
| } |
| } |