Skip to content

Commit 1342306

Browse files
romank-msftliuw
authored andcommitted
arm64: kvm, smccc: Introduce and use API for getting hypervisor UUID
The KVM/arm64 uses SMCCC to detect hypervisor presence. That code is private, and it follows the SMCCC specification. Other existing and emerging hypervisor guest implementations can and should use that standard approach as well. Factor out a common infrastructure that the guests can use, update KVM to employ the new API. The central notion of the SMCCC method is the UUID of the hypervisor, and the new API follows that. No functional changes. Validated with a KVM/arm64 guest. Signed-off-by: Roman Kisel <[email protected]> Acked-by: Arnd Bergmann <[email protected]> Reviewed-by: Michael Kelley <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Wei Liu <[email protected]> Message-ID: <[email protected]>
1 parent a9c0b33 commit 1342306

File tree

4 files changed

+85
-16
lines changed

4 files changed

+85
-16
lines changed

arch/arm64/kvm/hypercalls.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,7 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)
270270
u32 feature;
271271
u8 action;
272272
gpa_t gpa;
273+
uuid_t uuid;
273274

274275
action = kvm_smccc_get_action(vcpu, func_id);
275276
switch (action) {
@@ -355,10 +356,11 @@ int kvm_smccc_call_handler(struct kvm_vcpu *vcpu)
355356
val[0] = gpa;
356357
break;
357358
case ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID:
358-
val[0] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0;
359-
val[1] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1;
360-
val[2] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2;
361-
val[3] = ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3;
359+
uuid = ARM_SMCCC_VENDOR_HYP_UID_KVM;
360+
val[0] = smccc_uuid_to_reg(&uuid, 0);
361+
val[1] = smccc_uuid_to_reg(&uuid, 1);
362+
val[2] = smccc_uuid_to_reg(&uuid, 2);
363+
val[3] = smccc_uuid_to_reg(&uuid, 3);
362364
break;
363365
case ARM_SMCCC_VENDOR_HYP_KVM_FEATURES_FUNC_ID:
364366
val[0] = smccc_feat->vendor_hyp_bmap;

drivers/firmware/smccc/kvm_guest.c

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,11 @@ static DECLARE_BITMAP(__kvm_arm_hyp_services, ARM_SMCCC_KVM_NUM_FUNCS) __ro_afte
1717

1818
void __init kvm_init_hyp_services(void)
1919
{
20+
uuid_t kvm_uuid = ARM_SMCCC_VENDOR_HYP_UID_KVM;
2021
struct arm_smccc_res res;
2122
u32 val[4];
2223

23-
if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_HVC)
24-
return;
25-
26-
arm_smccc_1_1_invoke(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
27-
if (res.a0 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0 ||
28-
res.a1 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1 ||
29-
res.a2 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2 ||
30-
res.a3 != ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3)
24+
if (!arm_smccc_hypervisor_has_uuid(&kvm_uuid))
3125
return;
3226

3327
memset(&res, 0, sizeof(res));

drivers/firmware/smccc/smccc.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,23 @@ s32 arm_smccc_get_soc_id_revision(void)
6767
}
6868
EXPORT_SYMBOL_GPL(arm_smccc_get_soc_id_revision);
6969

70+
bool arm_smccc_hypervisor_has_uuid(const uuid_t *hyp_uuid)
71+
{
72+
struct arm_smccc_res res = {};
73+
uuid_t uuid;
74+
75+
if (arm_smccc_1_1_get_conduit() != SMCCC_CONDUIT_HVC)
76+
return false;
77+
78+
arm_smccc_1_1_hvc(ARM_SMCCC_VENDOR_HYP_CALL_UID_FUNC_ID, &res);
79+
if (res.a0 == SMCCC_RET_NOT_SUPPORTED)
80+
return false;
81+
82+
uuid = smccc_res_to_uuid(res.a0, res.a1, res.a2, res.a3);
83+
return uuid_equal(&uuid, hyp_uuid);
84+
}
85+
EXPORT_SYMBOL_GPL(arm_smccc_hypervisor_has_uuid);
86+
7087
static int __init smccc_devices_init(void)
7188
{
7289
struct platform_device *pdev;

include/linux/arm-smccc.h

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77

88
#include <linux/args.h>
99
#include <linux/init.h>
10+
11+
#ifndef __ASSEMBLY__
12+
#include <linux/uuid.h>
13+
#endif
14+
1015
#include <uapi/linux/const.h>
1116

1217
/*
@@ -107,10 +112,10 @@
107112
ARM_SMCCC_FUNC_QUERY_CALL_UID)
108113

109114
/* KVM UID value: 28b46fb6-2ec5-11e9-a9ca-4b564d003a74 */
110-
#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_0 0xb66fb428U
111-
#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_1 0xe911c52eU
112-
#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_2 0x564bcaa9U
113-
#define ARM_SMCCC_VENDOR_HYP_UID_KVM_REG_3 0x743a004dU
115+
#define ARM_SMCCC_VENDOR_HYP_UID_KVM UUID_INIT(\
116+
0xb66fb428, 0xc52e, 0xe911, \
117+
0xa9, 0xca, 0x4b, 0x56, \
118+
0x4d, 0x00, 0x3a, 0x74)
114119

115120
/* KVM "vendor specific" services */
116121
#define ARM_SMCCC_KVM_FUNC_FEATURES 0
@@ -348,6 +353,57 @@ s32 arm_smccc_get_soc_id_version(void);
348353
*/
349354
s32 arm_smccc_get_soc_id_revision(void);
350355

356+
#ifndef __ASSEMBLY__
357+
358+
/*
359+
* Returns whether a specific hypervisor UUID is advertised for the
360+
* Vendor Specific Hypervisor Service range.
361+
*/
362+
bool arm_smccc_hypervisor_has_uuid(const uuid_t *uuid);
363+
364+
static inline uuid_t smccc_res_to_uuid(u32 r0, u32 r1, u32 r2, u32 r3)
365+
{
366+
uuid_t uuid = {
367+
.b = {
368+
[0] = (r0 >> 0) & 0xff,
369+
[1] = (r0 >> 8) & 0xff,
370+
[2] = (r0 >> 16) & 0xff,
371+
[3] = (r0 >> 24) & 0xff,
372+
373+
[4] = (r1 >> 0) & 0xff,
374+
[5] = (r1 >> 8) & 0xff,
375+
[6] = (r1 >> 16) & 0xff,
376+
[7] = (r1 >> 24) & 0xff,
377+
378+
[8] = (r2 >> 0) & 0xff,
379+
[9] = (r2 >> 8) & 0xff,
380+
[10] = (r2 >> 16) & 0xff,
381+
[11] = (r2 >> 24) & 0xff,
382+
383+
[12] = (r3 >> 0) & 0xff,
384+
[13] = (r3 >> 8) & 0xff,
385+
[14] = (r3 >> 16) & 0xff,
386+
[15] = (r3 >> 24) & 0xff,
387+
},
388+
};
389+
390+
return uuid;
391+
}
392+
393+
static inline u32 smccc_uuid_to_reg(const uuid_t *uuid, int reg)
394+
{
395+
u32 val = 0;
396+
397+
val |= (u32)(uuid->b[4 * reg + 0] << 0);
398+
val |= (u32)(uuid->b[4 * reg + 1] << 8);
399+
val |= (u32)(uuid->b[4 * reg + 2] << 16);
400+
val |= (u32)(uuid->b[4 * reg + 3] << 24);
401+
402+
return val;
403+
}
404+
405+
#endif /* !__ASSEMBLY__ */
406+
351407
/**
352408
* struct arm_smccc_res - Result from SMC/HVC call
353409
* @a0-a3 result values from registers 0 to 3

0 commit comments

Comments
 (0)