summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2018-02-06 12:56:12 -0500
committerCatalin Marinas <catalin.marinas@arm.com>2018-02-06 17:54:01 -0500
commit09e6be12effdb33bf7210c8867bbd213b66a499e (patch)
treeb0557bf7a9651f9207e7e278e3ee6d9917fc17d3
parent58e0b2239a4d997094ba63986ef4de29ddc91d87 (diff)
arm/arm64: KVM: Advertise SMCCC v1.1
The new SMC Calling Convention (v1.1) allows for a reduced overhead when calling into the firmware, and provides a new feature discovery mechanism. Make it visible to KVM guests. Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
-rw-r--r--arch/arm/kvm/handle_exit.c2
-rw-r--r--arch/arm64/kvm/handle_exit.c2
-rw-r--r--include/kvm/arm_psci.h2
-rw-r--r--include/linux/arm-smccc.h13
-rw-r--r--virt/kvm/arm/psci.c24
5 files changed, 39 insertions, 4 deletions
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index 230ae4079108..910bd8dabb3c 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -36,7 +36,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
36 kvm_vcpu_hvc_get_imm(vcpu)); 36 kvm_vcpu_hvc_get_imm(vcpu));
37 vcpu->stat.hvc_exit_stat++; 37 vcpu->stat.hvc_exit_stat++;
38 38
39 ret = kvm_psci_call(vcpu); 39 ret = kvm_hvc_call_handler(vcpu);
40 if (ret < 0) { 40 if (ret < 0) {
41 vcpu_set_reg(vcpu, 0, ~0UL); 41 vcpu_set_reg(vcpu, 0, ~0UL);
42 return 1; 42 return 1;
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 588f910632a7..e5e741bfffe1 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -52,7 +52,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
52 kvm_vcpu_hvc_get_imm(vcpu)); 52 kvm_vcpu_hvc_get_imm(vcpu));
53 vcpu->stat.hvc_exit_stat++; 53 vcpu->stat.hvc_exit_stat++;
54 54
55 ret = kvm_psci_call(vcpu); 55 ret = kvm_hvc_call_handler(vcpu);
56 if (ret < 0) { 56 if (ret < 0) {
57 vcpu_set_reg(vcpu, 0, ~0UL); 57 vcpu_set_reg(vcpu, 0, ~0UL);
58 return 1; 58 return 1;
diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h
index 32360432cff5..ed1dd8088f1c 100644
--- a/include/kvm/arm_psci.h
+++ b/include/kvm/arm_psci.h
@@ -27,6 +27,6 @@
27#define KVM_ARM_PSCI_LATEST KVM_ARM_PSCI_1_0 27#define KVM_ARM_PSCI_LATEST KVM_ARM_PSCI_1_0
28 28
29int kvm_psci_version(struct kvm_vcpu *vcpu); 29int kvm_psci_version(struct kvm_vcpu *vcpu);
30int kvm_psci_call(struct kvm_vcpu *vcpu); 30int kvm_hvc_call_handler(struct kvm_vcpu *vcpu);
31 31
32#endif /* __KVM_ARM_PSCI_H__ */ 32#endif /* __KVM_ARM_PSCI_H__ */
diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h
index 4c5bca38c653..dc68aa5a7261 100644
--- a/include/linux/arm-smccc.h
+++ b/include/linux/arm-smccc.h
@@ -60,6 +60,19 @@
60#define ARM_SMCCC_QUIRK_NONE 0 60#define ARM_SMCCC_QUIRK_NONE 0
61#define ARM_SMCCC_QUIRK_QCOM_A6 1 /* Save/restore register a6 */ 61#define ARM_SMCCC_QUIRK_QCOM_A6 1 /* Save/restore register a6 */
62 62
63#define ARM_SMCCC_VERSION_1_0 0x10000
64#define ARM_SMCCC_VERSION_1_1 0x10001
65
66#define ARM_SMCCC_VERSION_FUNC_ID \
67 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
68 ARM_SMCCC_SMC_32, \
69 0, 0)
70
71#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID \
72 ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \
73 ARM_SMCCC_SMC_32, \
74 0, 1)
75
63#ifndef __ASSEMBLY__ 76#ifndef __ASSEMBLY__
64 77
65#include <linux/linkage.h> 78#include <linux/linkage.h>
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index 3e7c63e15f04..46a98fee3ef5 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -15,6 +15,7 @@
15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18#include <linux/arm-smccc.h>
18#include <linux/preempt.h> 19#include <linux/preempt.h>
19#include <linux/kvm_host.h> 20#include <linux/kvm_host.h>
20#include <linux/wait.h> 21#include <linux/wait.h>
@@ -339,6 +340,7 @@ static int kvm_psci_1_0_call(struct kvm_vcpu *vcpu)
339 case PSCI_0_2_FN_SYSTEM_OFF: 340 case PSCI_0_2_FN_SYSTEM_OFF:
340 case PSCI_0_2_FN_SYSTEM_RESET: 341 case PSCI_0_2_FN_SYSTEM_RESET:
341 case PSCI_1_0_FN_PSCI_FEATURES: 342 case PSCI_1_0_FN_PSCI_FEATURES:
343 case ARM_SMCCC_VERSION_FUNC_ID:
342 val = 0; 344 val = 0;
343 break; 345 break;
344 default: 346 default:
@@ -393,7 +395,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu)
393 * Errors: 395 * Errors:
394 * -EINVAL: Unrecognized PSCI function 396 * -EINVAL: Unrecognized PSCI function
395 */ 397 */
396int kvm_psci_call(struct kvm_vcpu *vcpu) 398static int kvm_psci_call(struct kvm_vcpu *vcpu)
397{ 399{
398 switch (kvm_psci_version(vcpu)) { 400 switch (kvm_psci_version(vcpu)) {
399 case KVM_ARM_PSCI_1_0: 401 case KVM_ARM_PSCI_1_0:
@@ -406,3 +408,23 @@ int kvm_psci_call(struct kvm_vcpu *vcpu)
406 return -EINVAL; 408 return -EINVAL;
407 }; 409 };
408} 410}
411
412int kvm_hvc_call_handler(struct kvm_vcpu *vcpu)
413{
414 u32 func_id = smccc_get_function(vcpu);
415 u32 val = PSCI_RET_NOT_SUPPORTED;
416
417 switch (func_id) {
418 case ARM_SMCCC_VERSION_FUNC_ID:
419 val = ARM_SMCCC_VERSION_1_1;
420 break;
421 case ARM_SMCCC_ARCH_FEATURES_FUNC_ID:
422 /* Nothing supported yet */
423 break;
424 default:
425 return kvm_psci_call(vcpu);
426 }
427
428 smccc_set_retval(vcpu, val, 0, 0, 0);
429 return 1;
430}