smccc-call.S (3864B)
1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * Copyright (c) 2015, Linaro Limited 4 */ 5#include <linux/linkage.h> 6#include <linux/arm-smccc.h> 7 8#include <asm/asm-offsets.h> 9#include <asm/assembler.h> 10#include <asm/thread_info.h> 11 12/* 13 * If we have SMCCC v1.3 and (as is likely) no SVE state in 14 * the registers then set the SMCCC hint bit to say there's no 15 * need to preserve it. Do this by directly adjusting the SMCCC 16 * function value which is already stored in x0 ready to be called. 17 */ 18SYM_FUNC_START(__arm_smccc_sve_check) 19 20 ldr_l x16, smccc_has_sve_hint 21 cbz x16, 2f 22 23 get_current_task x16 24 ldr x16, [x16, #TSK_TI_FLAGS] 25 tbnz x16, #TIF_FOREIGN_FPSTATE, 1f // Any live FP state? 26 tbnz x16, #TIF_SVE, 2f // Does that state include SVE? 27 281: orr x0, x0, ARM_SMCCC_1_3_SVE_HINT 29 302: ret 31SYM_FUNC_END(__arm_smccc_sve_check) 32EXPORT_SYMBOL(__arm_smccc_sve_check) 33 34 .macro SMCCC instr 35 stp x29, x30, [sp, #-16]! 36 mov x29, sp 37alternative_if ARM64_SVE 38 bl __arm_smccc_sve_check 39alternative_else_nop_endif 40 \instr #0 41 ldr x4, [sp, #16] 42 stp x0, x1, [x4, #ARM_SMCCC_RES_X0_OFFS] 43 stp x2, x3, [x4, #ARM_SMCCC_RES_X2_OFFS] 44 ldr x4, [sp, #24] 45 cbz x4, 1f /* no quirk structure */ 46 ldr x9, [x4, #ARM_SMCCC_QUIRK_ID_OFFS] 47 cmp x9, #ARM_SMCCC_QUIRK_QCOM_A6 48 b.ne 1f 49 str x6, [x4, ARM_SMCCC_QUIRK_STATE_OFFS] 501: ldp x29, x30, [sp], #16 51 ret 52 .endm 53 54/* 55 * void arm_smccc_smc(unsigned long a0, unsigned long a1, unsigned long a2, 56 * unsigned long a3, unsigned long a4, unsigned long a5, 57 * unsigned long a6, unsigned long a7, struct arm_smccc_res *res, 58 * struct arm_smccc_quirk *quirk) 59 */ 60SYM_FUNC_START(__arm_smccc_smc) 61 SMCCC smc 62SYM_FUNC_END(__arm_smccc_smc) 63EXPORT_SYMBOL(__arm_smccc_smc) 64 65/* 66 * void arm_smccc_hvc(unsigned long a0, unsigned long a1, unsigned long a2, 67 * unsigned long a3, unsigned long a4, unsigned long a5, 68 * unsigned long a6, unsigned long a7, struct arm_smccc_res *res, 69 * struct arm_smccc_quirk *quirk) 70 */ 71SYM_FUNC_START(__arm_smccc_hvc) 72 SMCCC hvc 73SYM_FUNC_END(__arm_smccc_hvc) 74EXPORT_SYMBOL(__arm_smccc_hvc) 75 76 .macro SMCCC_1_2 instr 77 /* Save `res` and free a GPR that won't be clobbered */ 78 stp x1, x19, [sp, #-16]! 79 80 /* Ensure `args` won't be clobbered while loading regs in next step */ 81 mov x19, x0 82 83 /* Load the registers x0 - x17 from the struct arm_smccc_1_2_regs */ 84 ldp x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS] 85 ldp x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS] 86 ldp x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS] 87 ldp x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS] 88 ldp x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS] 89 ldp x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS] 90 ldp x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS] 91 ldp x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS] 92 ldp x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS] 93 94 \instr #0 95 96 /* Load the `res` from the stack */ 97 ldr x19, [sp] 98 99 /* Store the registers x0 - x17 into the result structure */ 100 stp x0, x1, [x19, #ARM_SMCCC_1_2_REGS_X0_OFFS] 101 stp x2, x3, [x19, #ARM_SMCCC_1_2_REGS_X2_OFFS] 102 stp x4, x5, [x19, #ARM_SMCCC_1_2_REGS_X4_OFFS] 103 stp x6, x7, [x19, #ARM_SMCCC_1_2_REGS_X6_OFFS] 104 stp x8, x9, [x19, #ARM_SMCCC_1_2_REGS_X8_OFFS] 105 stp x10, x11, [x19, #ARM_SMCCC_1_2_REGS_X10_OFFS] 106 stp x12, x13, [x19, #ARM_SMCCC_1_2_REGS_X12_OFFS] 107 stp x14, x15, [x19, #ARM_SMCCC_1_2_REGS_X14_OFFS] 108 stp x16, x17, [x19, #ARM_SMCCC_1_2_REGS_X16_OFFS] 109 110 /* Restore original x19 */ 111 ldp xzr, x19, [sp], #16 112 ret 113.endm 114 115/* 116 * void arm_smccc_1_2_hvc(const struct arm_smccc_1_2_regs *args, 117 * struct arm_smccc_1_2_regs *res); 118 */ 119SYM_FUNC_START(arm_smccc_1_2_hvc) 120 SMCCC_1_2 hvc 121SYM_FUNC_END(arm_smccc_1_2_hvc) 122EXPORT_SYMBOL(arm_smccc_1_2_hvc) 123 124/* 125 * void arm_smccc_1_2_smc(const struct arm_smccc_1_2_regs *args, 126 * struct arm_smccc_1_2_regs *res); 127 */ 128SYM_FUNC_START(arm_smccc_1_2_smc) 129 SMCCC_1_2 smc 130SYM_FUNC_END(arm_smccc_1_2_smc) 131EXPORT_SYMBOL(arm_smccc_1_2_smc)