@@ -380,6 +380,8 @@ static inline void eeh_add_sysfs_files(struct pci_bus *bus) { }
static inline void eeh_remove_device(struct pci_dev *dev) { }
+static inline void kvmppc_eeh_vfio_release(struct kvm *kvm) { }
+
#define EEH_POSSIBLE_ERROR(val, type) (0)
#define EEH_IO_ERROR_VALUE(size) (-1UL)
#endif /* CONFIG_EEH */
@@ -388,7 +390,9 @@ static inline void eeh_remove_device(struct pci_dev *dev) { }
#ifdef CONFIG_KVM_EEH
struct eeh_dev *eeh_vfio_dev_get(struct eeh_vfio_pci_addr *addr);
struct eeh_pe *eeh_vfio_pe_get(struct eeh_vfio_pci_addr *addr);
-
+void kvmppc_eeh_vfio_release(struct kvm *kvm);
+#else
+static inline void kvmppc_eeh_vfio_release(void *kvm) { };
#endif /* CONFIG_KVM_EEH */
#ifdef CONFIG_PPC64
@@ -331,6 +331,48 @@ struct eeh_dev *eeh_vfio_dev_get(struct eeh_vfio_pci_addr *addr)
return NULL;
}
+
+static void *__kvmppc_eeh_vfio_release(void *data, void *flag)
+{
+ struct eeh_pe *pe = (struct eeh_pe *)data;
+ struct kvm *kvm = (struct kvm *)flag;
+ struct eeh_dev *edev, *tmp;
+
+ if (!eeh_pe_passed(pe))
+ return NULL;
+
+ eeh_pe_for_each_dev(pe, edev, tmp) {
+ if (!eeh_dev_passed(edev))
+ continue;
+
+ if (edev->gaddr.kvm == kvm)
+ eeh_dev_set_passed(edev, false);
+ }
+
+ eeh_pe_set_passed(pe, false);
+
+ return NULL;
+}
+
+/**
+ * kvmppc_eeh_vfio_release - Release VFIO devices for the given VM
+ * @kvm: VM indicator
+ *
+ * The function is expected to be called while the VM is destroyed.
+ * In turn, the PCI devices that have been passed to that VM should
+ * be released and their address mapping maintained will be destroyed.
+ */
+void kvmppc_eeh_vfio_release(struct kvm *kvm)
+{
+ struct eeh_pe *root;
+ void *ret;
+
+ list_for_each_entry(root, &eeh_phb_pe, child) {
+ ret = eeh_pe_traverse(root, __kvmppc_eeh_vfio_release, kvm);
+ if (ret) return;
+ }
+}
+EXPORT_SYMBOL_GPL(kvmppc_eeh_vfio_release);
#endif /* CONFIG_KVM_EEH */
/**
@@ -49,6 +49,7 @@
#include <asm/hvcall.h>
#include <asm/switch_to.h>
#include <asm/smp.h>
+#include <asm/eeh.h>
#include <linux/gfp.h>
#include <linux/vmalloc.h>
#include <linux/highmem.h>
@@ -2344,6 +2345,7 @@ static void kvmppc_core_destroy_vm_hv(struct kvm *kvm)
kvm->arch.rma = NULL;
}
+ kvmppc_eeh_vfio_release(kvm);
kvmppc_free_hpt(kvm);
}
When the VM is destroyed, the EEH devices and PEs that have been marked as being owned by guest should be returned to host. The patch introduces kvmppc_vfio_pci_free() to do it. Signed-off-by: Gavin Shan <gwshan@linux.vnet.ibm.com> --- arch/powerpc/include/asm/eeh.h | 6 +++++- arch/powerpc/kernel/eeh_pe.c | 42 ++++++++++++++++++++++++++++++++++++++++++ arch/powerpc/kvm/book3s_hv.c | 2 ++ 3 files changed, 49 insertions(+), 1 deletion(-)