| .. | .. |
|---|
| 31 | 31 | */ |
|---|
| 32 | 32 | |
|---|
| 33 | 33 | #include <linux/types.h> |
|---|
| 34 | | -#include <xen/xen.h> |
|---|
| 35 | 34 | #include <linux/kthread.h> |
|---|
| 36 | 35 | |
|---|
| 37 | 36 | #include "i915_drv.h" |
|---|
| 37 | +#include "intel_gvt.h" |
|---|
| 38 | 38 | #include "gvt.h" |
|---|
| 39 | 39 | #include <linux/vfio.h> |
|---|
| 40 | 40 | #include <linux/mdev.h> |
|---|
| .. | .. |
|---|
| 49 | 49 | static struct intel_vgpu_type *intel_gvt_find_vgpu_type(struct intel_gvt *gvt, |
|---|
| 50 | 50 | const char *name) |
|---|
| 51 | 51 | { |
|---|
| 52 | + const char *driver_name = |
|---|
| 53 | + dev_driver_string(&gvt->gt->i915->drm.pdev->dev); |
|---|
| 52 | 54 | int i; |
|---|
| 53 | | - struct intel_vgpu_type *t; |
|---|
| 54 | | - const char *driver_name = dev_driver_string( |
|---|
| 55 | | - &gvt->dev_priv->drm.pdev->dev); |
|---|
| 56 | 55 | |
|---|
| 56 | + name += strlen(driver_name) + 1; |
|---|
| 57 | 57 | for (i = 0; i < gvt->num_types; i++) { |
|---|
| 58 | | - t = &gvt->types[i]; |
|---|
| 59 | | - if (!strncmp(t->name, name + strlen(driver_name) + 1, |
|---|
| 60 | | - sizeof(t->name))) |
|---|
| 58 | + struct intel_vgpu_type *t = &gvt->types[i]; |
|---|
| 59 | + |
|---|
| 60 | + if (!strncmp(t->name, name, sizeof(t->name))) |
|---|
| 61 | 61 | return t; |
|---|
| 62 | 62 | } |
|---|
| 63 | 63 | |
|---|
| .. | .. |
|---|
| 120 | 120 | [0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL, |
|---|
| 121 | 121 | }; |
|---|
| 122 | 122 | |
|---|
| 123 | | -static bool intel_get_gvt_attrs(struct attribute ***type_attrs, |
|---|
| 124 | | - struct attribute_group ***intel_vgpu_type_groups) |
|---|
| 123 | +static bool intel_get_gvt_attrs(struct attribute_group ***intel_vgpu_type_groups) |
|---|
| 125 | 124 | { |
|---|
| 126 | | - *type_attrs = gvt_type_attrs; |
|---|
| 127 | 125 | *intel_vgpu_type_groups = gvt_vgpu_type_groups; |
|---|
| 128 | 126 | return true; |
|---|
| 129 | 127 | } |
|---|
| .. | .. |
|---|
| 185 | 183 | .vgpu_query_plane = intel_vgpu_query_plane, |
|---|
| 186 | 184 | .vgpu_get_dmabuf = intel_vgpu_get_dmabuf, |
|---|
| 187 | 185 | .write_protect_handler = intel_vgpu_page_track_handler, |
|---|
| 186 | + .emulate_hotplug = intel_vgpu_emulate_hotplug, |
|---|
| 188 | 187 | }; |
|---|
| 189 | | - |
|---|
| 190 | | -/** |
|---|
| 191 | | - * intel_gvt_init_host - Load MPT modules and detect if we're running in host |
|---|
| 192 | | - * @gvt: intel gvt device |
|---|
| 193 | | - * |
|---|
| 194 | | - * This function is called at the driver loading stage. If failed to find a |
|---|
| 195 | | - * loadable MPT module or detect currently we're running in a VM, then GVT-g |
|---|
| 196 | | - * will be disabled |
|---|
| 197 | | - * |
|---|
| 198 | | - * Returns: |
|---|
| 199 | | - * Zero on success, negative error code if failed. |
|---|
| 200 | | - * |
|---|
| 201 | | - */ |
|---|
| 202 | | -int intel_gvt_init_host(void) |
|---|
| 203 | | -{ |
|---|
| 204 | | - if (intel_gvt_host.initialized) |
|---|
| 205 | | - return 0; |
|---|
| 206 | | - |
|---|
| 207 | | - /* Xen DOM U */ |
|---|
| 208 | | - if (xen_domain() && !xen_initial_domain()) |
|---|
| 209 | | - return -ENODEV; |
|---|
| 210 | | - |
|---|
| 211 | | - /* Try to load MPT modules for hypervisors */ |
|---|
| 212 | | - if (xen_initial_domain()) { |
|---|
| 213 | | - /* In Xen dom0 */ |
|---|
| 214 | | - intel_gvt_host.mpt = try_then_request_module( |
|---|
| 215 | | - symbol_get(xengt_mpt), "xengt"); |
|---|
| 216 | | - intel_gvt_host.hypervisor_type = INTEL_GVT_HYPERVISOR_XEN; |
|---|
| 217 | | - } else { |
|---|
| 218 | | -#if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT) |
|---|
| 219 | | - /* not in Xen. Try KVMGT */ |
|---|
| 220 | | - intel_gvt_host.mpt = try_then_request_module( |
|---|
| 221 | | - symbol_get(kvmgt_mpt), "kvmgt"); |
|---|
| 222 | | - intel_gvt_host.hypervisor_type = INTEL_GVT_HYPERVISOR_KVM; |
|---|
| 223 | | -#endif |
|---|
| 224 | | - } |
|---|
| 225 | | - |
|---|
| 226 | | - /* Fail to load MPT modules - bail out */ |
|---|
| 227 | | - if (!intel_gvt_host.mpt) |
|---|
| 228 | | - return -EINVAL; |
|---|
| 229 | | - |
|---|
| 230 | | - gvt_dbg_core("Running with hypervisor %s in host mode\n", |
|---|
| 231 | | - supported_hypervisors[intel_gvt_host.hypervisor_type]); |
|---|
| 232 | | - |
|---|
| 233 | | - intel_gvt_host.initialized = true; |
|---|
| 234 | | - return 0; |
|---|
| 235 | | -} |
|---|
| 236 | 188 | |
|---|
| 237 | 189 | static void init_device_info(struct intel_gvt *gvt) |
|---|
| 238 | 190 | { |
|---|
| 239 | 191 | struct intel_gvt_device_info *info = &gvt->device_info; |
|---|
| 240 | | - struct pci_dev *pdev = gvt->dev_priv->drm.pdev; |
|---|
| 192 | + struct pci_dev *pdev = gvt->gt->i915->drm.pdev; |
|---|
| 241 | 193 | |
|---|
| 242 | 194 | info->max_support_vgpus = 8; |
|---|
| 243 | 195 | info->cfg_space_size = PCI_CFG_SPACE_EXP_SIZE; |
|---|
| .. | .. |
|---|
| 303 | 255 | |
|---|
| 304 | 256 | /** |
|---|
| 305 | 257 | * intel_gvt_clean_device - clean a GVT device |
|---|
| 306 | | - * @gvt: intel gvt device |
|---|
| 258 | + * @i915: i915 private |
|---|
| 307 | 259 | * |
|---|
| 308 | 260 | * This function is called at the driver unloading stage, to free the |
|---|
| 309 | 261 | * resources owned by a GVT device. |
|---|
| 310 | 262 | * |
|---|
| 311 | 263 | */ |
|---|
| 312 | | -void intel_gvt_clean_device(struct drm_i915_private *dev_priv) |
|---|
| 264 | +void intel_gvt_clean_device(struct drm_i915_private *i915) |
|---|
| 313 | 265 | { |
|---|
| 314 | | - struct intel_gvt *gvt = to_gvt(dev_priv); |
|---|
| 266 | + struct intel_gvt *gvt = fetch_and_zero(&i915->gvt); |
|---|
| 315 | 267 | |
|---|
| 316 | | - if (WARN_ON(!gvt)) |
|---|
| 268 | + if (drm_WARN_ON(&i915->drm, !gvt)) |
|---|
| 317 | 269 | return; |
|---|
| 318 | 270 | |
|---|
| 319 | 271 | intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu); |
|---|
| 320 | | - intel_gvt_hypervisor_host_exit(&dev_priv->drm.pdev->dev, gvt); |
|---|
| 321 | 272 | intel_gvt_cleanup_vgpu_type_groups(gvt); |
|---|
| 322 | 273 | intel_gvt_clean_vgpu_types(gvt); |
|---|
| 323 | 274 | |
|---|
| .. | .. |
|---|
| 332 | 283 | intel_gvt_clean_mmio_info(gvt); |
|---|
| 333 | 284 | idr_destroy(&gvt->vgpu_idr); |
|---|
| 334 | 285 | |
|---|
| 335 | | - kfree(dev_priv->gvt); |
|---|
| 336 | | - dev_priv->gvt = NULL; |
|---|
| 286 | + kfree(i915->gvt); |
|---|
| 337 | 287 | } |
|---|
| 338 | 288 | |
|---|
| 339 | 289 | /** |
|---|
| 340 | 290 | * intel_gvt_init_device - initialize a GVT device |
|---|
| 341 | | - * @dev_priv: drm i915 private data |
|---|
| 291 | + * @i915: drm i915 private data |
|---|
| 342 | 292 | * |
|---|
| 343 | 293 | * This function is called at the initialization stage, to initialize |
|---|
| 344 | 294 | * necessary GVT components. |
|---|
| .. | .. |
|---|
| 347 | 297 | * Zero on success, negative error code if failed. |
|---|
| 348 | 298 | * |
|---|
| 349 | 299 | */ |
|---|
| 350 | | -int intel_gvt_init_device(struct drm_i915_private *dev_priv) |
|---|
| 300 | +int intel_gvt_init_device(struct drm_i915_private *i915) |
|---|
| 351 | 301 | { |
|---|
| 352 | 302 | struct intel_gvt *gvt; |
|---|
| 353 | 303 | struct intel_vgpu *vgpu; |
|---|
| 354 | 304 | int ret; |
|---|
| 355 | 305 | |
|---|
| 356 | | - /* |
|---|
| 357 | | - * Cannot initialize GVT device without intel_gvt_host gets |
|---|
| 358 | | - * initialized first. |
|---|
| 359 | | - */ |
|---|
| 360 | | - if (WARN_ON(!intel_gvt_host.initialized)) |
|---|
| 361 | | - return -EINVAL; |
|---|
| 362 | | - |
|---|
| 363 | | - if (WARN_ON(dev_priv->gvt)) |
|---|
| 306 | + if (drm_WARN_ON(&i915->drm, i915->gvt)) |
|---|
| 364 | 307 | return -EEXIST; |
|---|
| 365 | 308 | |
|---|
| 366 | 309 | gvt = kzalloc(sizeof(struct intel_gvt), GFP_KERNEL); |
|---|
| .. | .. |
|---|
| 373 | 316 | spin_lock_init(&gvt->scheduler.mmio_context_lock); |
|---|
| 374 | 317 | mutex_init(&gvt->lock); |
|---|
| 375 | 318 | mutex_init(&gvt->sched_lock); |
|---|
| 376 | | - gvt->dev_priv = dev_priv; |
|---|
| 319 | + gvt->gt = &i915->gt; |
|---|
| 320 | + i915->gvt = gvt; |
|---|
| 377 | 321 | |
|---|
| 378 | 322 | init_device_info(gvt); |
|---|
| 379 | 323 | |
|---|
| .. | .. |
|---|
| 421 | 365 | goto out_clean_types; |
|---|
| 422 | 366 | } |
|---|
| 423 | 367 | |
|---|
| 424 | | - ret = intel_gvt_hypervisor_host_init(&dev_priv->drm.pdev->dev, gvt, |
|---|
| 425 | | - &intel_gvt_ops); |
|---|
| 426 | | - if (ret) { |
|---|
| 427 | | - gvt_err("failed to register gvt-g host device: %d\n", ret); |
|---|
| 428 | | - goto out_clean_types; |
|---|
| 429 | | - } |
|---|
| 430 | | - |
|---|
| 431 | 368 | vgpu = intel_gvt_create_idle_vgpu(gvt); |
|---|
| 432 | 369 | if (IS_ERR(vgpu)) { |
|---|
| 433 | 370 | ret = PTR_ERR(vgpu); |
|---|
| .. | .. |
|---|
| 436 | 373 | } |
|---|
| 437 | 374 | gvt->idle_vgpu = vgpu; |
|---|
| 438 | 375 | |
|---|
| 439 | | - ret = intel_gvt_debugfs_init(gvt); |
|---|
| 440 | | - if (ret) |
|---|
| 441 | | - gvt_err("debugfs registeration failed, go on.\n"); |
|---|
| 376 | + intel_gvt_debugfs_init(gvt); |
|---|
| 442 | 377 | |
|---|
| 443 | 378 | gvt_dbg_core("gvt device initialization is done\n"); |
|---|
| 444 | | - dev_priv->gvt = gvt; |
|---|
| 379 | + intel_gvt_host.dev = &i915->drm.pdev->dev; |
|---|
| 380 | + intel_gvt_host.initialized = true; |
|---|
| 445 | 381 | return 0; |
|---|
| 446 | 382 | |
|---|
| 447 | 383 | out_clean_types: |
|---|
| .. | .. |
|---|
| 465 | 401 | out_clean_idr: |
|---|
| 466 | 402 | idr_destroy(&gvt->vgpu_idr); |
|---|
| 467 | 403 | kfree(gvt); |
|---|
| 404 | + i915->gvt = NULL; |
|---|
| 468 | 405 | return ret; |
|---|
| 469 | 406 | } |
|---|
| 470 | 407 | |
|---|
| 471 | | -#if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT) |
|---|
| 472 | | -MODULE_SOFTDEP("pre: kvmgt"); |
|---|
| 473 | | -#endif |
|---|
| 408 | +int |
|---|
| 409 | +intel_gvt_pm_resume(struct intel_gvt *gvt) |
|---|
| 410 | +{ |
|---|
| 411 | + intel_gvt_restore_fence(gvt); |
|---|
| 412 | + intel_gvt_restore_mmio(gvt); |
|---|
| 413 | + intel_gvt_restore_ggtt(gvt); |
|---|
| 414 | + return 0; |
|---|
| 415 | +} |
|---|
| 416 | + |
|---|
| 417 | +int |
|---|
| 418 | +intel_gvt_register_hypervisor(struct intel_gvt_mpt *m) |
|---|
| 419 | +{ |
|---|
| 420 | + int ret; |
|---|
| 421 | + void *gvt; |
|---|
| 422 | + |
|---|
| 423 | + if (!intel_gvt_host.initialized) |
|---|
| 424 | + return -ENODEV; |
|---|
| 425 | + |
|---|
| 426 | + if (m->type != INTEL_GVT_HYPERVISOR_KVM && |
|---|
| 427 | + m->type != INTEL_GVT_HYPERVISOR_XEN) |
|---|
| 428 | + return -EINVAL; |
|---|
| 429 | + |
|---|
| 430 | + /* Get a reference for device model module */ |
|---|
| 431 | + if (!try_module_get(THIS_MODULE)) |
|---|
| 432 | + return -ENODEV; |
|---|
| 433 | + |
|---|
| 434 | + intel_gvt_host.mpt = m; |
|---|
| 435 | + intel_gvt_host.hypervisor_type = m->type; |
|---|
| 436 | + gvt = (void *)kdev_to_i915(intel_gvt_host.dev)->gvt; |
|---|
| 437 | + |
|---|
| 438 | + ret = intel_gvt_hypervisor_host_init(intel_gvt_host.dev, gvt, |
|---|
| 439 | + &intel_gvt_ops); |
|---|
| 440 | + if (ret < 0) { |
|---|
| 441 | + gvt_err("Failed to init %s hypervisor module\n", |
|---|
| 442 | + supported_hypervisors[intel_gvt_host.hypervisor_type]); |
|---|
| 443 | + module_put(THIS_MODULE); |
|---|
| 444 | + return -ENODEV; |
|---|
| 445 | + } |
|---|
| 446 | + gvt_dbg_core("Running with hypervisor %s in host mode\n", |
|---|
| 447 | + supported_hypervisors[intel_gvt_host.hypervisor_type]); |
|---|
| 448 | + return 0; |
|---|
| 449 | +} |
|---|
| 450 | +EXPORT_SYMBOL_GPL(intel_gvt_register_hypervisor); |
|---|
| 451 | + |
|---|
| 452 | +void |
|---|
| 453 | +intel_gvt_unregister_hypervisor(void) |
|---|
| 454 | +{ |
|---|
| 455 | + intel_gvt_hypervisor_host_exit(intel_gvt_host.dev); |
|---|
| 456 | + module_put(THIS_MODULE); |
|---|
| 457 | +} |
|---|
| 458 | +EXPORT_SYMBOL_GPL(intel_gvt_unregister_hypervisor); |
|---|