diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h
index 6bda945..8dcd642 100644
--- a/arch/arm/include/asm/kvm_psci.h
+++ b/arch/arm/include/asm/kvm_psci.h
@@ -22,6 +22,7 @@
 #define KVM_ARM_PSCI_0_2       2

 int kvm_psci_version(struct kvm_vcpu *vcpu);
+bool kvm_psci_is_call(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);

 #endif /* __ARM_KVM_PSCI_H__ */
diff --git a/arch/arm64/include/asm/kvm_psci.h b/arch/arm64/include/asm/kvm_psci.h
index bc39e55..1a28809 100644
--- a/arch/arm64/include/asm/kvm_psci.h
+++ b/arch/arm64/include/asm/kvm_psci.h
@@ -22,6 +22,7 @@
 #define KVM_ARM_PSCI_0_2       2

 int kvm_psci_version(struct kvm_vcpu *vcpu);
+bool kvm_psci_is_call(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);

 #endif /* __ARM64_KVM_PSCI_H__ */
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 17d8a16..bc7ade5 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -21,6 +21,7 @@

 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <linux/smccc_fn.h>

 #include <asm/esr.h>
 #include <asm/kvm_asm.h>
@@ -34,19 +35,30 @@

 typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);

+/*
+ * handle_hvc - handle a guest hypercall
+ *
+ * @vcpu:      the vcpu pointer
+ * @run:       access to the kvm_run structure for results
+ *
+ * Route a given hypercall to its right HVC handler thanks to its function ID.
+ * If no corresponding handler is found, write an Unknown ID in x0 (cf. SMCCC).
+ *
+ * This function returns: > 0 (success), 0 (success but exit to user
+ * space), and < 0 (errors)
+ */
 static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
-       int ret;
+       int ret = 1;

        trace_kvm_hvc_arm64(*vcpu_pc(vcpu), vcpu_get_reg(vcpu, 0),
                            kvm_vcpu_hvc_get_imm(vcpu));
        vcpu->stat.hvc_exit_stat++;

-       ret = kvm_psci_call(vcpu);
-       if (ret < 0) {
-               kvm_inject_undefined(vcpu);
-               return 1;
-       }
+       if (kvm_psci_is_call(vcpu))
+               ret = kvm_psci_call(vcpu);
+       else
+               vcpu_set_reg(vcpu, 0, SMCCC_STD_RET_UNKNOWN_ID);

        return ret;
 }
diff --git a/include/uapi/linux/psci.h b/include/uapi/linux/psci.h
index 3d7a0fc..79704fe 100644
--- a/include/uapi/linux/psci.h
+++ b/include/uapi/linux/psci.h
@@ -24,10 +24,12 @@
 /* PSCI v0.2 interface */
 #define PSCI_0_2_FN_BASE                       0x84000000
 #define PSCI_0_2_FN(n)                         (PSCI_0_2_FN_BASE + (n))
+#define PSCI_0_2_FN_END                                PSCI_0_2_FN(0x1F)
 #define PSCI_0_2_64BIT                         0x40000000
 #define PSCI_0_2_FN64_BASE                     \
                                        (PSCI_0_2_FN_BASE + PSCI_0_2_64BIT)
 #define PSCI_0_2_FN64(n)                       (PSCI_0_2_FN64_BASE + (n))
+#define PSCI_0_2_FN64_END                      PSCI_0_2_FN64(0x1F)

 #define PSCI_0_2_FN_PSCI_VERSION               PSCI_0_2_FN(0)
 #define PSCI_0_2_FN_CPU_SUSPEND                        PSCI_0_2_FN(1)
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index f1e363b..9602894 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -332,3 +332,24 @@ int kvm_psci_call(struct kvm_vcpu *vcpu)
                return -EINVAL;
        };
 }
+
+/**
+ * kvm_psci_is_call - checks if a HVC function ID is in a PSCI range
+ * @vcpu: Pointer to the VCPU struct
+ *
+ * When a hypercall is received from a guest. The SMCCC defines a function ID
+ * as a value to be put in x0 to identify the destination of the call. The same
+ * document defines ranges of function IDs to be used by PSCI. This function
+ * checks whether a given vcpu is requesting a PSCI related handler.
+ *
+ * This function returns:
+ *  - true if this HVC should be handled by kvm_psci_call
+ *  - false if it shouldn't
+ */
+inline bool kvm_psci_is_call(struct kvm_vcpu *vcpu)
+{
+       unsigned long fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0);
+
+       return ((fn >= PSCI_0_2_FN_BASE   && fn <= PSCI_0_2_FN_END) ||
+               (fn >= PSCI_0_2_FN64_BASE && fn <= PSCI_0_2_FN64_END));
+}
