From: Paul Mackerras <pau...@ozlabs.org>

commit 2ad7a27deaf6d78545d97ab80874584f6990360e upstream.

There are some POWER9 machines where the OPAL firmware does not support
the OPAL_XIVE_GET_QUEUE_STATE and OPAL_XIVE_SET_QUEUE_STATE calls.
The impact of this is that a guest using XIVE natively will not be able
to be migrated successfully.  On the source side, the get_attr operation
on the KVM native device for the KVM_DEV_XIVE_GRP_EQ_CONFIG attribute
will fail; on the destination side, the set_attr operation for the same
attribute will fail.

This adds tests for the existence of the OPAL get/set queue state
functions, and if they are not supported, the XIVE-native KVM device
is not created and the KVM_CAP_PPC_IRQ_XIVE capability returns false.
Userspace can then either provide a software emulation of XIVE, or
else tell the guest that it does not have a XIVE controller available
to it.

Cc: sta...@vger.kernel.org # v5.2+
Fixes: 3fab2d10588e ("KVM: PPC: Book3S HV: XIVE: Activate XIVE exploitation 
mode")
Reviewed-by: David Gibson <da...@gibson.dropbear.id.au>
Reviewed-by: Cédric Le Goater <c...@kaod.org>
Signed-off-by: Paul Mackerras <pau...@ozlabs.org>
Signed-off-by: Greg Kroah-Hartman <gre...@linuxfoundation.org>

---
 arch/powerpc/include/asm/kvm_ppc.h    |    1 +
 arch/powerpc/include/asm/xive.h       |    1 +
 arch/powerpc/kvm/book3s.c             |    8 +++++---
 arch/powerpc/kvm/book3s_xive_native.c |    5 +++++
 arch/powerpc/kvm/powerpc.c            |    3 ++-
 arch/powerpc/sysdev/xive/native.c     |    7 +++++++
 6 files changed, 21 insertions(+), 4 deletions(-)

--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -598,6 +598,7 @@ extern int kvmppc_xive_native_get_vp(str
                                     union kvmppc_one_reg *val);
 extern int kvmppc_xive_native_set_vp(struct kvm_vcpu *vcpu,
                                     union kvmppc_one_reg *val);
+extern bool kvmppc_xive_native_supported(void);
 
 #else
 static inline int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server,
--- a/arch/powerpc/include/asm/xive.h
+++ b/arch/powerpc/include/asm/xive.h
@@ -127,6 +127,7 @@ extern int xive_native_get_queue_state(u
 extern int xive_native_set_queue_state(u32 vp_id, uint32_t prio, u32 qtoggle,
                                       u32 qindex);
 extern int xive_native_get_vp_state(u32 vp_id, u64 *out_state);
+extern bool xive_native_has_queue_state_support(void);
 
 #else
 
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -1083,9 +1083,11 @@ static int kvmppc_book3s_init(void)
        if (xics_on_xive()) {
                kvmppc_xive_init_module();
                kvm_register_device_ops(&kvm_xive_ops, KVM_DEV_TYPE_XICS);
-               kvmppc_xive_native_init_module();
-               kvm_register_device_ops(&kvm_xive_native_ops,
-                                       KVM_DEV_TYPE_XIVE);
+               if (kvmppc_xive_native_supported()) {
+                       kvmppc_xive_native_init_module();
+                       kvm_register_device_ops(&kvm_xive_native_ops,
+                                               KVM_DEV_TYPE_XIVE);
+               }
        } else
 #endif
                kvm_register_device_ops(&kvm_xics_ops, KVM_DEV_TYPE_XICS);
--- a/arch/powerpc/kvm/book3s_xive_native.c
+++ b/arch/powerpc/kvm/book3s_xive_native.c
@@ -1171,6 +1171,11 @@ int kvmppc_xive_native_set_vp(struct kvm
        return 0;
 }
 
+bool kvmppc_xive_native_supported(void)
+{
+       return xive_native_has_queue_state_support();
+}
+
 static int xive_native_debug_show(struct seq_file *m, void *private)
 {
        struct kvmppc_xive *xive = m->private;
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -561,7 +561,8 @@ int kvm_vm_ioctl_check_extension(struct
                 * a POWER9 processor) and the PowerNV platform, as
                 * nested is not yet supported.
                 */
-               r = xive_enabled() && !!cpu_has_feature(CPU_FTR_HVMODE);
+               r = xive_enabled() && !!cpu_has_feature(CPU_FTR_HVMODE) &&
+                       kvmppc_xive_native_supported();
                break;
 #endif
 
--- a/arch/powerpc/sysdev/xive/native.c
+++ b/arch/powerpc/sysdev/xive/native.c
@@ -811,6 +811,13 @@ int xive_native_set_queue_state(u32 vp_i
 }
 EXPORT_SYMBOL_GPL(xive_native_set_queue_state);
 
+bool xive_native_has_queue_state_support(void)
+{
+       return opal_check_token(OPAL_XIVE_GET_QUEUE_STATE) &&
+               opal_check_token(OPAL_XIVE_SET_QUEUE_STATE);
+}
+EXPORT_SYMBOL_GPL(xive_native_has_queue_state_support);
+
 int xive_native_get_vp_state(u32 vp_id, u64 *out_state)
 {
        __be64 state;


Reply via email to