关于SMC instruction指令执行level的讨论

前段时间在分析kvm armv8部分源码的时候,发现一个很奇怪的smcc指令

include/linux/arm-smccc.h

arm_smccc_1_1_invoke

 *
399  * This is a variadic macro taking one to eight source arguments, and
400  * an optional return structure.
401  *
402  * @a0-a7: arguments passed in registers 0 to 7
403  * @res: result values from registers 0 to 3
404  *
405  * This macro will make either an HVC call or an SMC call depending on the
406  * current SMCCC conduit. If no valid conduit is available then -1
407  * (SMCCC_RET_NOT_SUPPORTED) is returned in @res.a0 (if supplied).
408  *
409  * The return value also provides the conduit that was used.
410  */
411 #define arm_smccc_1_1_invoke(...) ({                                    \
412                 int method = arm_smccc_1_1_get_conduit();               \
413                 switch (method) {                                       \
414                 case SMCCC_CONDUIT_HVC:                                 \
415                         arm_smccc_1_1_hvc(__VA_ARGS__);                 \
416                         break;                                          \
417                 case SMCCC_CONDUIT_SMC:   // 不太明白为什么在EL1状态能执行SMC指令能够有效。\
418                         arm_smccc_1_1_smc(__VA_ARGS__);                 \
419                         break;                                          \
420                 default:                                                \
421                         __fail_smccc_1_1(__VA_ARGS__);                  \
422                         method = SMCCC_CONDUIT_NONE;                    \
423                         break;                                          \
424                 }                                                       \
425                 method;                                                 \
426         })
427
428 #endif /*__ASSEMBLY__*/

 

337 #define __arm_smccc_1_1(inst, ...)                                      \
338         do {                                                            \
339                 register unsigned long r0 asm("r0");                    \
340                 register unsigned long r1 asm("r1");                    \
341                 register unsigned long r2 asm("r2");                    \
342                 register unsigned long r3 asm("r3");                    \
343                 __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \
344                 asm volatile(inst "\n" :                                \
345                              "=r" (r0), "=r" (r1), "=r" (r2), "=r" (r3) \
346                              __constraints(__count_args(__VA_ARGS__))); \
347                 if (___res)                                             \
348                         *___res = (typeof(*___res)){r0, r1, r2, r3};    \
349         } while (0)
350
351 /*
352  * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call
353  *
354  * This is a variadic macro taking one to eight source arguments, and
355  * an optional return structure.
356  *
357  * @a0-a7: arguments passed in registers 0 to 7
358  * @res: result values from registers 0 to 3
359  *
360  * This macro is used to make SMC calls following SMC Calling Convention v1.1.
361  * The content of the supplied param are copied to registers 0 to 7 prior
362  * to the SMC instruction. The return values are updated with the content
363  * from register 0 to 3 on return from the SMC instruction if not NULL.
364  */
365 #define arm_smccc_1_1_smc(...)  __arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__)

当时kernel正好作为guest os运行在EL1上,觉得很奇怪的是,为什么EL1状态下能trap smccc指令进入到

EL3状态,觉得很疑惑,就查找了下手册,找到了如下解释才弄明白。

The SMC instruction is used to generate a synchronous exception that is handled by Secure Monitor code running in EL3.

Arguments and return values are passed in registers. After being handled by the Secure Monitor, calls that result from the i

nstructions can be passed on to a Trusted OS or some other entity in the secure software stack.

 

 

The HVC instruction is used to generate a synchronous exception that is handled by a hypervisor running in EL2.

Arguments and return values are passed in registers. Hypervisors can also trap SMC calls that are made by Guest Operating

Systems (at EL1), which allows the calls to be emulated, passed through, or denied as appropriate.

 

Hypervisors can also trap SMC calls that are made by Guest Operating Systems (at EL1), which allows the calls

to be emulated, passed through, or denied as appropriate.

 

参考:ARM_DEN0028B_SMC_Calling_Convention.pdf

 

posted @ 2021-04-04 17:37  haoxing990  阅读(1098)  评论(0编辑  收藏  举报