root/drivers/gpu/drm/i915/gvt/gvt.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. intel_gvt_find_vgpu_type
  2. available_instances_show
  3. device_api_show
  4. description_show
  5. intel_get_gvt_attrs
  6. intel_gvt_init_vgpu_type_groups
  7. intel_gvt_cleanup_vgpu_type_groups
  8. init_device_info
  9. gvt_service_thread
  10. clean_service_thread
  11. init_service_thread
  12. intel_gvt_clean_device
  13. intel_gvt_init_device
  14. intel_gvt_register_hypervisor
  15. intel_gvt_unregister_hypervisor

   1 /*
   2  * Copyright(c) 2011-2016 Intel Corporation. All rights reserved.
   3  *
   4  * Permission is hereby granted, free of charge, to any person obtaining a
   5  * copy of this software and associated documentation files (the "Software"),
   6  * to deal in the Software without restriction, including without limitation
   7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8  * and/or sell copies of the Software, and to permit persons to whom the
   9  * Software is furnished to do so, subject to the following conditions:
  10  *
  11  * The above copyright notice and this permission notice (including the next
  12  * paragraph) shall be included in all copies or substantial portions of the
  13  * Software.
  14  *
  15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21  * SOFTWARE.
  22  *
  23  * Authors:
  24  *    Kevin Tian <kevin.tian@intel.com>
  25  *    Eddie Dong <eddie.dong@intel.com>
  26  *
  27  * Contributors:
  28  *    Niu Bing <bing.niu@intel.com>
  29  *    Zhi Wang <zhi.a.wang@intel.com>
  30  *
  31  */
  32 
  33 #include <linux/types.h>
  34 #include <xen/xen.h>
  35 #include <linux/kthread.h>
  36 
  37 #include "i915_drv.h"
  38 #include "gvt.h"
  39 #include <linux/vfio.h>
  40 #include <linux/mdev.h>
  41 
  42 struct intel_gvt_host intel_gvt_host;
  43 
  44 static const char * const supported_hypervisors[] = {
  45         [INTEL_GVT_HYPERVISOR_XEN] = "XEN",
  46         [INTEL_GVT_HYPERVISOR_KVM] = "KVM",
  47 };
  48 
  49 static struct intel_vgpu_type *intel_gvt_find_vgpu_type(struct intel_gvt *gvt,
  50                 const char *name)
  51 {
  52         int i;
  53         struct intel_vgpu_type *t;
  54         const char *driver_name = dev_driver_string(
  55                         &gvt->dev_priv->drm.pdev->dev);
  56 
  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)))
  61                         return t;
  62         }
  63 
  64         return NULL;
  65 }
  66 
  67 static ssize_t available_instances_show(struct kobject *kobj,
  68                                         struct device *dev, char *buf)
  69 {
  70         struct intel_vgpu_type *type;
  71         unsigned int num = 0;
  72         void *gvt = kdev_to_i915(dev)->gvt;
  73 
  74         type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj));
  75         if (!type)
  76                 num = 0;
  77         else
  78                 num = type->avail_instance;
  79 
  80         return sprintf(buf, "%u\n", num);
  81 }
  82 
  83 static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
  84                 char *buf)
  85 {
  86         return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
  87 }
  88 
  89 static ssize_t description_show(struct kobject *kobj, struct device *dev,
  90                 char *buf)
  91 {
  92         struct intel_vgpu_type *type;
  93         void *gvt = kdev_to_i915(dev)->gvt;
  94 
  95         type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj));
  96         if (!type)
  97                 return 0;
  98 
  99         return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n"
 100                        "fence: %d\nresolution: %s\n"
 101                        "weight: %d\n",
 102                        BYTES_TO_MB(type->low_gm_size),
 103                        BYTES_TO_MB(type->high_gm_size),
 104                        type->fence, vgpu_edid_str(type->resolution),
 105                        type->weight);
 106 }
 107 
 108 static MDEV_TYPE_ATTR_RO(available_instances);
 109 static MDEV_TYPE_ATTR_RO(device_api);
 110 static MDEV_TYPE_ATTR_RO(description);
 111 
 112 static struct attribute *gvt_type_attrs[] = {
 113         &mdev_type_attr_available_instances.attr,
 114         &mdev_type_attr_device_api.attr,
 115         &mdev_type_attr_description.attr,
 116         NULL,
 117 };
 118 
 119 static struct attribute_group *gvt_vgpu_type_groups[] = {
 120         [0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL,
 121 };
 122 
 123 static bool intel_get_gvt_attrs(struct attribute ***type_attrs,
 124                 struct attribute_group ***intel_vgpu_type_groups)
 125 {
 126         *type_attrs = gvt_type_attrs;
 127         *intel_vgpu_type_groups = gvt_vgpu_type_groups;
 128         return true;
 129 }
 130 
 131 static bool intel_gvt_init_vgpu_type_groups(struct intel_gvt *gvt)
 132 {
 133         int i, j;
 134         struct intel_vgpu_type *type;
 135         struct attribute_group *group;
 136 
 137         for (i = 0; i < gvt->num_types; i++) {
 138                 type = &gvt->types[i];
 139 
 140                 group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
 141                 if (WARN_ON(!group))
 142                         goto unwind;
 143 
 144                 group->name = type->name;
 145                 group->attrs = gvt_type_attrs;
 146                 gvt_vgpu_type_groups[i] = group;
 147         }
 148 
 149         return true;
 150 
 151 unwind:
 152         for (j = 0; j < i; j++) {
 153                 group = gvt_vgpu_type_groups[j];
 154                 kfree(group);
 155         }
 156 
 157         return false;
 158 }
 159 
 160 static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt)
 161 {
 162         int i;
 163         struct attribute_group *group;
 164 
 165         for (i = 0; i < gvt->num_types; i++) {
 166                 group = gvt_vgpu_type_groups[i];
 167                 gvt_vgpu_type_groups[i] = NULL;
 168                 kfree(group);
 169         }
 170 }
 171 
 172 static const struct intel_gvt_ops intel_gvt_ops = {
 173         .emulate_cfg_read = intel_vgpu_emulate_cfg_read,
 174         .emulate_cfg_write = intel_vgpu_emulate_cfg_write,
 175         .emulate_mmio_read = intel_vgpu_emulate_mmio_read,
 176         .emulate_mmio_write = intel_vgpu_emulate_mmio_write,
 177         .vgpu_create = intel_gvt_create_vgpu,
 178         .vgpu_destroy = intel_gvt_destroy_vgpu,
 179         .vgpu_release = intel_gvt_release_vgpu,
 180         .vgpu_reset = intel_gvt_reset_vgpu,
 181         .vgpu_activate = intel_gvt_activate_vgpu,
 182         .vgpu_deactivate = intel_gvt_deactivate_vgpu,
 183         .gvt_find_vgpu_type = intel_gvt_find_vgpu_type,
 184         .get_gvt_attrs = intel_get_gvt_attrs,
 185         .vgpu_query_plane = intel_vgpu_query_plane,
 186         .vgpu_get_dmabuf = intel_vgpu_get_dmabuf,
 187         .write_protect_handler = intel_vgpu_page_track_handler,
 188         .emulate_hotplug = intel_vgpu_emulate_hotplug,
 189 };
 190 
 191 static void init_device_info(struct intel_gvt *gvt)
 192 {
 193         struct intel_gvt_device_info *info = &gvt->device_info;
 194         struct pci_dev *pdev = gvt->dev_priv->drm.pdev;
 195 
 196         info->max_support_vgpus = 8;
 197         info->cfg_space_size = PCI_CFG_SPACE_EXP_SIZE;
 198         info->mmio_size = 2 * 1024 * 1024;
 199         info->mmio_bar = 0;
 200         info->gtt_start_offset = 8 * 1024 * 1024;
 201         info->gtt_entry_size = 8;
 202         info->gtt_entry_size_shift = 3;
 203         info->gmadr_bytes_in_cmd = 8;
 204         info->max_surface_size = 36 * 1024 * 1024;
 205         info->msi_cap_offset = pdev->msi_cap;
 206 }
 207 
 208 static int gvt_service_thread(void *data)
 209 {
 210         struct intel_gvt *gvt = (struct intel_gvt *)data;
 211         int ret;
 212 
 213         gvt_dbg_core("service thread start\n");
 214 
 215         while (!kthread_should_stop()) {
 216                 ret = wait_event_interruptible(gvt->service_thread_wq,
 217                                 kthread_should_stop() || gvt->service_request);
 218 
 219                 if (kthread_should_stop())
 220                         break;
 221 
 222                 if (WARN_ONCE(ret, "service thread is waken up by signal.\n"))
 223                         continue;
 224 
 225                 if (test_and_clear_bit(INTEL_GVT_REQUEST_EMULATE_VBLANK,
 226                                         (void *)&gvt->service_request))
 227                         intel_gvt_emulate_vblank(gvt);
 228 
 229                 if (test_bit(INTEL_GVT_REQUEST_SCHED,
 230                                 (void *)&gvt->service_request) ||
 231                         test_bit(INTEL_GVT_REQUEST_EVENT_SCHED,
 232                                         (void *)&gvt->service_request)) {
 233                         intel_gvt_schedule(gvt);
 234                 }
 235         }
 236 
 237         return 0;
 238 }
 239 
 240 static void clean_service_thread(struct intel_gvt *gvt)
 241 {
 242         kthread_stop(gvt->service_thread);
 243 }
 244 
 245 static int init_service_thread(struct intel_gvt *gvt)
 246 {
 247         init_waitqueue_head(&gvt->service_thread_wq);
 248 
 249         gvt->service_thread = kthread_run(gvt_service_thread,
 250                         gvt, "gvt_service_thread");
 251         if (IS_ERR(gvt->service_thread)) {
 252                 gvt_err("fail to start service thread.\n");
 253                 return PTR_ERR(gvt->service_thread);
 254         }
 255         return 0;
 256 }
 257 
 258 /**
 259  * intel_gvt_clean_device - clean a GVT device
 260  * @dev_priv: i915 private
 261  *
 262  * This function is called at the driver unloading stage, to free the
 263  * resources owned by a GVT device.
 264  *
 265  */
 266 void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
 267 {
 268         struct intel_gvt *gvt = to_gvt(dev_priv);
 269 
 270         if (WARN_ON(!gvt))
 271                 return;
 272 
 273         intel_gvt_destroy_idle_vgpu(gvt->idle_vgpu);
 274         intel_gvt_cleanup_vgpu_type_groups(gvt);
 275         intel_gvt_clean_vgpu_types(gvt);
 276 
 277         intel_gvt_debugfs_clean(gvt);
 278         clean_service_thread(gvt);
 279         intel_gvt_clean_cmd_parser(gvt);
 280         intel_gvt_clean_sched_policy(gvt);
 281         intel_gvt_clean_workload_scheduler(gvt);
 282         intel_gvt_clean_gtt(gvt);
 283         intel_gvt_clean_irq(gvt);
 284         intel_gvt_free_firmware(gvt);
 285         intel_gvt_clean_mmio_info(gvt);
 286         idr_destroy(&gvt->vgpu_idr);
 287 
 288         kfree(dev_priv->gvt);
 289         dev_priv->gvt = NULL;
 290 }
 291 
 292 /**
 293  * intel_gvt_init_device - initialize a GVT device
 294  * @dev_priv: drm i915 private data
 295  *
 296  * This function is called at the initialization stage, to initialize
 297  * necessary GVT components.
 298  *
 299  * Returns:
 300  * Zero on success, negative error code if failed.
 301  *
 302  */
 303 int intel_gvt_init_device(struct drm_i915_private *dev_priv)
 304 {
 305         struct intel_gvt *gvt;
 306         struct intel_vgpu *vgpu;
 307         int ret;
 308 
 309         if (WARN_ON(dev_priv->gvt))
 310                 return -EEXIST;
 311 
 312         gvt = kzalloc(sizeof(struct intel_gvt), GFP_KERNEL);
 313         if (!gvt)
 314                 return -ENOMEM;
 315 
 316         gvt_dbg_core("init gvt device\n");
 317 
 318         idr_init(&gvt->vgpu_idr);
 319         spin_lock_init(&gvt->scheduler.mmio_context_lock);
 320         mutex_init(&gvt->lock);
 321         mutex_init(&gvt->sched_lock);
 322         gvt->dev_priv = dev_priv;
 323 
 324         init_device_info(gvt);
 325 
 326         ret = intel_gvt_setup_mmio_info(gvt);
 327         if (ret)
 328                 goto out_clean_idr;
 329 
 330         intel_gvt_init_engine_mmio_context(gvt);
 331 
 332         ret = intel_gvt_load_firmware(gvt);
 333         if (ret)
 334                 goto out_clean_mmio_info;
 335 
 336         ret = intel_gvt_init_irq(gvt);
 337         if (ret)
 338                 goto out_free_firmware;
 339 
 340         ret = intel_gvt_init_gtt(gvt);
 341         if (ret)
 342                 goto out_clean_irq;
 343 
 344         ret = intel_gvt_init_workload_scheduler(gvt);
 345         if (ret)
 346                 goto out_clean_gtt;
 347 
 348         ret = intel_gvt_init_sched_policy(gvt);
 349         if (ret)
 350                 goto out_clean_workload_scheduler;
 351 
 352         ret = intel_gvt_init_cmd_parser(gvt);
 353         if (ret)
 354                 goto out_clean_sched_policy;
 355 
 356         ret = init_service_thread(gvt);
 357         if (ret)
 358                 goto out_clean_cmd_parser;
 359 
 360         ret = intel_gvt_init_vgpu_types(gvt);
 361         if (ret)
 362                 goto out_clean_thread;
 363 
 364         ret = intel_gvt_init_vgpu_type_groups(gvt);
 365         if (ret == false) {
 366                 gvt_err("failed to init vgpu type groups: %d\n", ret);
 367                 goto out_clean_types;
 368         }
 369 
 370         vgpu = intel_gvt_create_idle_vgpu(gvt);
 371         if (IS_ERR(vgpu)) {
 372                 ret = PTR_ERR(vgpu);
 373                 gvt_err("failed to create idle vgpu\n");
 374                 goto out_clean_types;
 375         }
 376         gvt->idle_vgpu = vgpu;
 377 
 378         intel_gvt_debugfs_init(gvt);
 379 
 380         gvt_dbg_core("gvt device initialization is done\n");
 381         dev_priv->gvt = gvt;
 382         intel_gvt_host.dev = &dev_priv->drm.pdev->dev;
 383         intel_gvt_host.initialized = true;
 384         return 0;
 385 
 386 out_clean_types:
 387         intel_gvt_clean_vgpu_types(gvt);
 388 out_clean_thread:
 389         clean_service_thread(gvt);
 390 out_clean_cmd_parser:
 391         intel_gvt_clean_cmd_parser(gvt);
 392 out_clean_sched_policy:
 393         intel_gvt_clean_sched_policy(gvt);
 394 out_clean_workload_scheduler:
 395         intel_gvt_clean_workload_scheduler(gvt);
 396 out_clean_gtt:
 397         intel_gvt_clean_gtt(gvt);
 398 out_clean_irq:
 399         intel_gvt_clean_irq(gvt);
 400 out_free_firmware:
 401         intel_gvt_free_firmware(gvt);
 402 out_clean_mmio_info:
 403         intel_gvt_clean_mmio_info(gvt);
 404 out_clean_idr:
 405         idr_destroy(&gvt->vgpu_idr);
 406         kfree(gvt);
 407         return ret;
 408 }
 409 
 410 int
 411 intel_gvt_register_hypervisor(struct intel_gvt_mpt *m)
 412 {
 413         int ret;
 414         void *gvt;
 415 
 416         if (!intel_gvt_host.initialized)
 417                 return -ENODEV;
 418 
 419         if (m->type != INTEL_GVT_HYPERVISOR_KVM &&
 420             m->type != INTEL_GVT_HYPERVISOR_XEN)
 421                 return -EINVAL;
 422 
 423         /* Get a reference for device model module */
 424         if (!try_module_get(THIS_MODULE))
 425                 return -ENODEV;
 426 
 427         intel_gvt_host.mpt = m;
 428         intel_gvt_host.hypervisor_type = m->type;
 429         gvt = (void *)kdev_to_i915(intel_gvt_host.dev)->gvt;
 430 
 431         ret = intel_gvt_hypervisor_host_init(intel_gvt_host.dev, gvt,
 432                                              &intel_gvt_ops);
 433         if (ret < 0) {
 434                 gvt_err("Failed to init %s hypervisor module\n",
 435                         supported_hypervisors[intel_gvt_host.hypervisor_type]);
 436                 module_put(THIS_MODULE);
 437                 return -ENODEV;
 438         }
 439         gvt_dbg_core("Running with hypervisor %s in host mode\n",
 440                      supported_hypervisors[intel_gvt_host.hypervisor_type]);
 441         return 0;
 442 }
 443 EXPORT_SYMBOL_GPL(intel_gvt_register_hypervisor);
 444 
 445 void
 446 intel_gvt_unregister_hypervisor(void)
 447 {
 448         intel_gvt_hypervisor_host_exit(intel_gvt_host.dev);
 449         module_put(THIS_MODULE);
 450 }
 451 EXPORT_SYMBOL_GPL(intel_gvt_unregister_hypervisor);

/* [<][>][^][v][top][bottom][index][help] */