diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2018-02-06 12:56:12 -0500 |
---|---|---|
committer | Catalin Marinas <catalin.marinas@arm.com> | 2018-02-06 17:54:01 -0500 |
commit | 09e6be12effdb33bf7210c8867bbd213b66a499e (patch) | |
tree | b0557bf7a9651f9207e7e278e3ee6d9917fc17d3 | |
parent | 58e0b2239a4d997094ba63986ef4de29ddc91d87 (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.c | 2 | ||||
-rw-r--r-- | arch/arm64/kvm/handle_exit.c | 2 | ||||
-rw-r--r-- | include/kvm/arm_psci.h | 2 | ||||
-rw-r--r-- | include/linux/arm-smccc.h | 13 | ||||
-rw-r--r-- | virt/kvm/arm/psci.c | 24 |
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 | ||
29 | int kvm_psci_version(struct kvm_vcpu *vcpu); | 29 | int kvm_psci_version(struct kvm_vcpu *vcpu); |
30 | int kvm_psci_call(struct kvm_vcpu *vcpu); | 30 | int 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 | */ |
396 | int kvm_psci_call(struct kvm_vcpu *vcpu) | 398 | static 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 | |||
412 | int 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 | } | ||