drm/i915/gvt: Change KVMGT as self load module
This trys to make 'kvmgt' module as self loadable instead of loading by i915/gvt device model. So hypervisor specific module could be stand-alone, e.g only after loading hypervisor specific module, GVT feature could be enabled via specific hypervisor interface, e.g VFIO/mdev. So this trys to use hypervisor module register/unregister interface for that. Hypervisor module needs to take care of module reference itself when working for hypervisor interface, e.g for VFIO/mdev, hypervisor module would reference counting mdev when open and release. This makes 'kvmgt' module really split from GVT device model. User needs to load 'kvmgt' to enable VFIO/mdev interface. v6: - remove unused variable v5: - put module reference in register error path v4: - fix checkpatch warning v3: - Fix module reference handling for device open and release. Unused mdev devices would be cleaned up in device unregister when module unload. v2: - Fix kvmgt order after i915 for built-in case Cc: "Yuan, Hang" <hang.yuan@intel.com> Cc: Alex Williamson <alex.williamson@redhat.com> Cc: "He, Min" <min.he@intel.com> Reviewed-by: Yuan, Hang <hang.yuan@intel.com> Acked-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Signed-off-by: Zhenyu Wang <zhenyuw@linux.intel.com>
This commit is contained in:
parent
a2b8419a9e
commit
9bdb073464
@ -198,3 +198,4 @@ endif
|
||||
i915-y += intel_lpe_audio.o
|
||||
|
||||
obj-$(CONFIG_DRM_I915) += i915.o
|
||||
obj-$(CONFIG_DRM_I915_GVT_KVMGT) += gvt/kvmgt.o
|
||||
|
@ -7,4 +7,3 @@ GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \
|
||||
|
||||
ccflags-y += -I$(src) -I$(src)/$(GVT_DIR)
|
||||
i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
|
||||
obj-$(CONFIG_DRM_I915_GVT_KVMGT) += $(GVT_DIR)/kvmgt.o
|
||||
|
@ -187,52 +187,6 @@ static const struct intel_gvt_ops intel_gvt_ops = {
|
||||
.write_protect_handler = intel_vgpu_page_track_handler,
|
||||
};
|
||||
|
||||
/**
|
||||
* intel_gvt_init_host - Load MPT modules and detect if we're running in host
|
||||
*
|
||||
* This function is called at the driver loading stage. If failed to find a
|
||||
* loadable MPT module or detect currently we're running in a VM, then GVT-g
|
||||
* will be disabled
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, negative error code if failed.
|
||||
*
|
||||
*/
|
||||
int intel_gvt_init_host(void)
|
||||
{
|
||||
if (intel_gvt_host.initialized)
|
||||
return 0;
|
||||
|
||||
/* Xen DOM U */
|
||||
if (xen_domain() && !xen_initial_domain())
|
||||
return -ENODEV;
|
||||
|
||||
/* Try to load MPT modules for hypervisors */
|
||||
if (xen_initial_domain()) {
|
||||
/* In Xen dom0 */
|
||||
intel_gvt_host.mpt = try_then_request_module(
|
||||
symbol_get(xengt_mpt), "xengt");
|
||||
intel_gvt_host.hypervisor_type = INTEL_GVT_HYPERVISOR_XEN;
|
||||
} else {
|
||||
#if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT)
|
||||
/* not in Xen. Try KVMGT */
|
||||
intel_gvt_host.mpt = try_then_request_module(
|
||||
symbol_get(kvmgt_mpt), "kvmgt");
|
||||
intel_gvt_host.hypervisor_type = INTEL_GVT_HYPERVISOR_KVM;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Fail to load MPT modules - bail out */
|
||||
if (!intel_gvt_host.mpt)
|
||||
return -EINVAL;
|
||||
|
||||
gvt_dbg_core("Running with hypervisor %s in host mode\n",
|
||||
supported_hypervisors[intel_gvt_host.hypervisor_type]);
|
||||
|
||||
intel_gvt_host.initialized = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void init_device_info(struct intel_gvt *gvt)
|
||||
{
|
||||
struct intel_gvt_device_info *info = &gvt->device_info;
|
||||
@ -316,7 +270,6 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
|
||||
return;
|
||||
|
||||
intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);
|
||||
intel_gvt_hypervisor_host_exit(&dev_priv->drm.pdev->dev);
|
||||
intel_gvt_cleanup_vgpu_type_groups(gvt);
|
||||
intel_gvt_clean_vgpu_types(gvt);
|
||||
|
||||
@ -352,13 +305,6 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
|
||||
struct intel_vgpu *vgpu;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Cannot initialize GVT device without intel_gvt_host gets
|
||||
* initialized first.
|
||||
*/
|
||||
if (WARN_ON(!intel_gvt_host.initialized))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(dev_priv->gvt))
|
||||
return -EEXIST;
|
||||
|
||||
@ -420,13 +366,6 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
|
||||
goto out_clean_types;
|
||||
}
|
||||
|
||||
ret = intel_gvt_hypervisor_host_init(&dev_priv->drm.pdev->dev, gvt,
|
||||
&intel_gvt_ops);
|
||||
if (ret) {
|
||||
gvt_err("failed to register gvt-g host device: %d\n", ret);
|
||||
goto out_clean_types;
|
||||
}
|
||||
|
||||
vgpu = intel_gvt_create_idle_vgpu(gvt);
|
||||
if (IS_ERR(vgpu)) {
|
||||
ret = PTR_ERR(vgpu);
|
||||
@ -441,6 +380,8 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
|
||||
|
||||
gvt_dbg_core("gvt device initialization is done\n");
|
||||
dev_priv->gvt = gvt;
|
||||
intel_gvt_host.dev = &dev_priv->drm.pdev->dev;
|
||||
intel_gvt_host.initialized = true;
|
||||
return 0;
|
||||
|
||||
out_clean_types:
|
||||
@ -467,6 +408,45 @@ out_clean_idr:
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT)
|
||||
MODULE_SOFTDEP("pre: kvmgt");
|
||||
#endif
|
||||
int
|
||||
intel_gvt_register_hypervisor(struct intel_gvt_mpt *m)
|
||||
{
|
||||
int ret;
|
||||
void *gvt;
|
||||
|
||||
if (!intel_gvt_host.initialized)
|
||||
return -ENODEV;
|
||||
|
||||
if (m->type != INTEL_GVT_HYPERVISOR_KVM &&
|
||||
m->type != INTEL_GVT_HYPERVISOR_XEN)
|
||||
return -EINVAL;
|
||||
|
||||
/* Get a reference for device model module */
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
return -ENODEV;
|
||||
|
||||
intel_gvt_host.mpt = m;
|
||||
intel_gvt_host.hypervisor_type = m->type;
|
||||
gvt = (void *)kdev_to_i915(intel_gvt_host.dev)->gvt;
|
||||
|
||||
ret = intel_gvt_hypervisor_host_init(intel_gvt_host.dev, gvt,
|
||||
&intel_gvt_ops);
|
||||
if (ret < 0) {
|
||||
gvt_err("Failed to init %s hypervisor module\n",
|
||||
supported_hypervisors[intel_gvt_host.hypervisor_type]);
|
||||
module_put(THIS_MODULE);
|
||||
return -ENODEV;
|
||||
}
|
||||
gvt_dbg_core("Running with hypervisor %s in host mode\n",
|
||||
supported_hypervisors[intel_gvt_host.hypervisor_type]);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_gvt_register_hypervisor);
|
||||
|
||||
void
|
||||
intel_gvt_unregister_hypervisor(void)
|
||||
{
|
||||
intel_gvt_hypervisor_host_exit(intel_gvt_host.dev);
|
||||
module_put(THIS_MODULE);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(intel_gvt_unregister_hypervisor);
|
||||
|
@ -52,12 +52,8 @@
|
||||
|
||||
#define GVT_MAX_VGPU 8
|
||||
|
||||
enum {
|
||||
INTEL_GVT_HYPERVISOR_XEN = 0,
|
||||
INTEL_GVT_HYPERVISOR_KVM,
|
||||
};
|
||||
|
||||
struct intel_gvt_host {
|
||||
struct device *dev;
|
||||
bool initialized;
|
||||
int hypervisor_type;
|
||||
struct intel_gvt_mpt *mpt;
|
||||
|
@ -33,11 +33,17 @@
|
||||
#ifndef _GVT_HYPERCALL_H_
|
||||
#define _GVT_HYPERCALL_H_
|
||||
|
||||
enum hypervisor_type {
|
||||
INTEL_GVT_HYPERVISOR_XEN = 0,
|
||||
INTEL_GVT_HYPERVISOR_KVM,
|
||||
};
|
||||
|
||||
/*
|
||||
* Specific GVT-g MPT modules function collections. Currently GVT-g supports
|
||||
* both Xen and KVM by providing dedicated hypervisor-related MPT modules.
|
||||
*/
|
||||
struct intel_gvt_mpt {
|
||||
enum hypervisor_type type;
|
||||
int (*host_init)(struct device *dev, void *gvt, const void *ops);
|
||||
void (*host_exit)(struct device *dev);
|
||||
int (*attach_vgpu)(void *vgpu, unsigned long *handle);
|
||||
@ -67,6 +73,5 @@ struct intel_gvt_mpt {
|
||||
};
|
||||
|
||||
extern struct intel_gvt_mpt xengt_mpt;
|
||||
extern struct intel_gvt_mpt kvmgt_mpt;
|
||||
|
||||
#endif /* _GVT_HYPERCALL_H_ */
|
||||
|
@ -627,6 +627,12 @@ static int intel_vgpu_open(struct mdev_device *mdev)
|
||||
goto undo_iommu;
|
||||
}
|
||||
|
||||
/* Take a module reference as mdev core doesn't take
|
||||
* a reference for vendor driver.
|
||||
*/
|
||||
if (!try_module_get(THIS_MODULE))
|
||||
goto undo_group;
|
||||
|
||||
ret = kvmgt_guest_init(mdev);
|
||||
if (ret)
|
||||
goto undo_group;
|
||||
@ -679,6 +685,9 @@ static void __intel_vgpu_release(struct intel_vgpu *vgpu)
|
||||
&vgpu->vdev.group_notifier);
|
||||
WARN(ret, "vfio_unregister_notifier for group failed: %d\n", ret);
|
||||
|
||||
/* dereference module reference taken at open */
|
||||
module_put(THIS_MODULE);
|
||||
|
||||
info = (struct kvmgt_guest_info *)vgpu->handle;
|
||||
kvmgt_guest_exit(info);
|
||||
|
||||
@ -1849,7 +1858,8 @@ static bool kvmgt_is_valid_gfn(unsigned long handle, unsigned long gfn)
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct intel_gvt_mpt kvmgt_mpt = {
|
||||
static struct intel_gvt_mpt kvmgt_mpt = {
|
||||
.type = INTEL_GVT_HYPERVISOR_KVM,
|
||||
.host_init = kvmgt_host_init,
|
||||
.host_exit = kvmgt_host_exit,
|
||||
.attach_vgpu = kvmgt_attach_vgpu,
|
||||
@ -1868,15 +1878,17 @@ struct intel_gvt_mpt kvmgt_mpt = {
|
||||
.put_vfio_device = kvmgt_put_vfio_device,
|
||||
.is_valid_gfn = kvmgt_is_valid_gfn,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(kvmgt_mpt);
|
||||
|
||||
static int __init kvmgt_init(void)
|
||||
{
|
||||
if (intel_gvt_register_hypervisor(&kvmgt_mpt) < 0)
|
||||
return -ENODEV;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit kvmgt_exit(void)
|
||||
{
|
||||
intel_gvt_unregister_hypervisor();
|
||||
}
|
||||
|
||||
module_init(kvmgt_init);
|
||||
|
@ -360,4 +360,7 @@ static inline bool intel_gvt_hypervisor_is_valid_gfn(
|
||||
return intel_gvt_host.mpt->is_valid_gfn(vgpu->handle, gfn);
|
||||
}
|
||||
|
||||
int intel_gvt_register_hypervisor(struct intel_gvt_mpt *);
|
||||
void intel_gvt_unregister_hypervisor(void);
|
||||
|
||||
#endif /* _GVT_MPT_H_ */
|
||||
|
@ -105,15 +105,6 @@ int intel_gvt_init(struct drm_i915_private *dev_priv)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
/*
|
||||
* We're not in host or fail to find a MPT module, disable GVT-g
|
||||
*/
|
||||
ret = intel_gvt_init_host();
|
||||
if (ret) {
|
||||
DRM_DEBUG_DRIVER("Not in host or MPT modules not found\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
ret = intel_gvt_init_device(dev_priv);
|
||||
if (ret) {
|
||||
DRM_DEBUG_DRIVER("Fail to init GVT device\n");
|
||||
|
Loading…
Reference in New Issue
Block a user