1 |
From foo@baz Tue Mar 8 08:47:19 PM CET 2022 |
2 |
From: James Morse <james.morse@arm.com> |
3 |
Date: Fri, 10 Dec 2021 11:16:18 +0000 |
4 |
Subject: KVM: arm64: Allow SMCCC_ARCH_WORKAROUND_3 to be discovered and migrated |
5 |
|
6 |
From: James Morse <james.morse@arm.com> |
7 |
|
8 |
commit a5905d6af492ee6a4a2205f0d550b3f931b03d03 upstream. |
9 |
|
10 |
KVM allows the guest to discover whether the ARCH_WORKAROUND SMCCC are |
11 |
implemented, and to preserve that state during migration through its |
12 |
firmware register interface. |
13 |
|
14 |
Add the necessary boiler plate for SMCCC_ARCH_WORKAROUND_3. |
15 |
|
16 |
Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> |
17 |
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com> |
18 |
Signed-off-by: James Morse <james.morse@arm.com> |
19 |
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
20 |
--- |
21 |
arch/arm64/include/uapi/asm/kvm.h | 5 +++++ |
22 |
arch/arm64/kvm/hypercalls.c | 12 ++++++++++++ |
23 |
arch/arm64/kvm/psci.c | 18 +++++++++++++++++- |
24 |
3 files changed, 34 insertions(+), 1 deletion(-) |
25 |
|
26 |
--- a/arch/arm64/include/uapi/asm/kvm.h |
27 |
+++ b/arch/arm64/include/uapi/asm/kvm.h |
28 |
@@ -281,6 +281,11 @@ struct kvm_arm_copy_mte_tags { |
29 |
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_REQUIRED 3 |
30 |
#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_ENABLED (1U << 4) |
31 |
|
32 |
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3 KVM_REG_ARM_FW_REG(3) |
33 |
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL 0 |
34 |
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_AVAIL 1 |
35 |
+#define KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_REQUIRED 2 |
36 |
+ |
37 |
/* SVE registers */ |
38 |
#define KVM_REG_ARM64_SVE (0x15 << KVM_REG_ARM_COPROC_SHIFT) |
39 |
|
40 |
--- a/arch/arm64/kvm/hypercalls.c |
41 |
+++ b/arch/arm64/kvm/hypercalls.c |
42 |
@@ -107,6 +107,18 @@ int kvm_hvc_call_handler(struct kvm_vcpu |
43 |
break; |
44 |
} |
45 |
break; |
46 |
+ case ARM_SMCCC_ARCH_WORKAROUND_3: |
47 |
+ switch (arm64_get_spectre_bhb_state()) { |
48 |
+ case SPECTRE_VULNERABLE: |
49 |
+ break; |
50 |
+ case SPECTRE_MITIGATED: |
51 |
+ val[0] = SMCCC_RET_SUCCESS; |
52 |
+ break; |
53 |
+ case SPECTRE_UNAFFECTED: |
54 |
+ val[0] = SMCCC_ARCH_WORKAROUND_RET_UNAFFECTED; |
55 |
+ break; |
56 |
+ } |
57 |
+ break; |
58 |
case ARM_SMCCC_HV_PV_TIME_FEATURES: |
59 |
val[0] = SMCCC_RET_SUCCESS; |
60 |
break; |
61 |
--- a/arch/arm64/kvm/psci.c |
62 |
+++ b/arch/arm64/kvm/psci.c |
63 |
@@ -406,7 +406,7 @@ int kvm_psci_call(struct kvm_vcpu *vcpu) |
64 |
|
65 |
int kvm_arm_get_fw_num_regs(struct kvm_vcpu *vcpu) |
66 |
{ |
67 |
- return 3; /* PSCI version and two workaround registers */ |
68 |
+ return 4; /* PSCI version and three workaround registers */ |
69 |
} |
70 |
|
71 |
int kvm_arm_copy_fw_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices) |
72 |
@@ -420,6 +420,9 @@ int kvm_arm_copy_fw_reg_indices(struct k |
73 |
if (put_user(KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2, uindices++)) |
74 |
return -EFAULT; |
75 |
|
76 |
+ if (put_user(KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3, uindices++)) |
77 |
+ return -EFAULT; |
78 |
+ |
79 |
return 0; |
80 |
} |
81 |
|
82 |
@@ -459,6 +462,17 @@ static int get_kernel_wa_level(u64 regid |
83 |
case SPECTRE_VULNERABLE: |
84 |
return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2_NOT_AVAIL; |
85 |
} |
86 |
+ break; |
87 |
+ case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3: |
88 |
+ switch (arm64_get_spectre_bhb_state()) { |
89 |
+ case SPECTRE_VULNERABLE: |
90 |
+ return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL; |
91 |
+ case SPECTRE_MITIGATED: |
92 |
+ return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_AVAIL; |
93 |
+ case SPECTRE_UNAFFECTED: |
94 |
+ return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_REQUIRED; |
95 |
+ } |
96 |
+ return KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3_NOT_AVAIL; |
97 |
} |
98 |
|
99 |
return -EINVAL; |
100 |
@@ -475,6 +489,7 @@ int kvm_arm_get_fw_reg(struct kvm_vcpu * |
101 |
break; |
102 |
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1: |
103 |
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_2: |
104 |
+ case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3: |
105 |
val = get_kernel_wa_level(reg->id) & KVM_REG_FEATURE_LEVEL_MASK; |
106 |
break; |
107 |
default: |
108 |
@@ -520,6 +535,7 @@ int kvm_arm_set_fw_reg(struct kvm_vcpu * |
109 |
} |
110 |
|
111 |
case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_1: |
112 |
+ case KVM_REG_ARM_SMCCC_ARCH_WORKAROUND_3: |
113 |
if (val & ~KVM_REG_FEATURE_LEVEL_MASK) |
114 |
return -EINVAL; |
115 |
|