Commit 3dd435ef authored by Rodrigo Vivi's avatar Rodrigo Vivi

Merge tag 'gvt-next-2017-11-16' of https://github.com/intel/gvt-linux into drm-intel-next-queued

gvt-next-2017-11-16

- CSB HWSP update support (Weinan)
- GVT debug helpers, dyndbg and debugfs (Chuanxiao, Shuo)
- full virtualized opregion (Xiaolin)
- VM health check for sane fallback (Fred)
- workload submission code refactor for future enabling (Zhi)
- Updated repo URL in MAINTAINERS (Zhenyu)
- other many misc fixes
Signed-off-by: default avatarRodrigo Vivi <rodrigo.vivi@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20171116092007.ww5bvfx7rf36bjmn@zhen-hp.sh.intel.com
parents 9672a69c f2880e04
......@@ -6928,7 +6928,7 @@ M: Zhi Wang <zhi.a.wang@intel.com>
L: intel-gvt-dev@lists.freedesktop.org
L: intel-gfx@lists.freedesktop.org
W: https://01.org/igvt-g
T: git https://github.com/01org/gvt-linux.git
T: git https://github.com/intel/gvt-linux.git
S: Supported
F: drivers/gpu/drm/i915/gvt/
......
GVT_DIR := gvt
GVT_SOURCE := gvt.o aperture_gm.o handlers.o vgpu.o trace_points.o firmware.o \
interrupt.o gtt.o cfg_space.o opregion.o mmio.o display.o edid.o \
execlist.o scheduler.o sched_policy.o render.o cmd_parser.o
execlist.o scheduler.o sched_policy.o render.o cmd_parser.o debugfs.o
ccflags-y += -I$(src) -I$(src)/$(GVT_DIR)
i915-y += $(addprefix $(GVT_DIR)/, $(GVT_SOURCE))
......
......@@ -208,6 +208,20 @@ static int emulate_pci_command_write(struct intel_vgpu *vgpu,
return 0;
}
static int emulate_pci_rom_bar_write(struct intel_vgpu *vgpu,
unsigned int offset, void *p_data, unsigned int bytes)
{
u32 *pval = (u32 *)(vgpu_cfg_space(vgpu) + offset);
u32 new = *(u32 *)(p_data);
if ((new & PCI_ROM_ADDRESS_MASK) == PCI_ROM_ADDRESS_MASK)
/* We don't have rom, return size of 0. */
*pval = 0;
else
vgpu_pci_cfg_mem_write(vgpu, offset, p_data, bytes);
return 0;
}
static int emulate_pci_bar_write(struct intel_vgpu *vgpu, unsigned int offset,
void *p_data, unsigned int bytes)
{
......@@ -300,6 +314,11 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
}
switch (rounddown(offset, 4)) {
case PCI_ROM_ADDRESS:
if (WARN_ON(!IS_ALIGNED(offset, 4)))
return -EINVAL;
return emulate_pci_rom_bar_write(vgpu, offset, p_data, bytes);
case PCI_BASE_ADDRESS_0 ... PCI_BASE_ADDRESS_5:
if (WARN_ON(!IS_ALIGNED(offset, 4)))
return -EINVAL;
......@@ -375,6 +394,8 @@ void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu,
pci_resource_len(gvt->dev_priv->drm.pdev, 0);
vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].size =
pci_resource_len(gvt->dev_priv->drm.pdev, 2);
memset(vgpu_cfg_space(vgpu) + PCI_ROM_ADDRESS, 0, 4);
}
/**
......
This diff is collapsed.
......@@ -25,41 +25,41 @@
#define __GVT_DEBUG_H__
#define gvt_err(fmt, args...) \
DRM_ERROR("gvt: "fmt, ##args)
pr_err("gvt: "fmt, ##args)
#define gvt_vgpu_err(fmt, args...) \
do { \
if (IS_ERR_OR_NULL(vgpu)) \
DRM_DEBUG_DRIVER("gvt: "fmt, ##args); \
pr_err("gvt: "fmt, ##args); \
else \
DRM_DEBUG_DRIVER("gvt: vgpu %d: "fmt, vgpu->id, ##args);\
pr_err("gvt: vgpu %d: "fmt, vgpu->id, ##args);\
} while (0)
#define gvt_dbg_core(fmt, args...) \
DRM_DEBUG_DRIVER("gvt: core: "fmt, ##args)
pr_debug("gvt: core: "fmt, ##args)
#define gvt_dbg_irq(fmt, args...) \
DRM_DEBUG_DRIVER("gvt: irq: "fmt, ##args)
pr_debug("gvt: irq: "fmt, ##args)
#define gvt_dbg_mm(fmt, args...) \
DRM_DEBUG_DRIVER("gvt: mm: "fmt, ##args)
pr_debug("gvt: mm: "fmt, ##args)
#define gvt_dbg_mmio(fmt, args...) \
DRM_DEBUG_DRIVER("gvt: mmio: "fmt, ##args)
pr_debug("gvt: mmio: "fmt, ##args)
#define gvt_dbg_dpy(fmt, args...) \
DRM_DEBUG_DRIVER("gvt: dpy: "fmt, ##args)
pr_debug("gvt: dpy: "fmt, ##args)
#define gvt_dbg_el(fmt, args...) \
DRM_DEBUG_DRIVER("gvt: el: "fmt, ##args)
pr_debug("gvt: el: "fmt, ##args)
#define gvt_dbg_sched(fmt, args...) \
DRM_DEBUG_DRIVER("gvt: sched: "fmt, ##args)
pr_debug("gvt: sched: "fmt, ##args)
#define gvt_dbg_render(fmt, args...) \
DRM_DEBUG_DRIVER("gvt: render: "fmt, ##args)
pr_debug("gvt: render: "fmt, ##args)
#define gvt_dbg_cmd(fmt, args...) \
DRM_DEBUG_DRIVER("gvt: cmd: "fmt, ##args)
pr_debug("gvt: cmd: "fmt, ##args)
#endif
/*
* Copyright(c) 2011-2017 Intel Corporation. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include <linux/debugfs.h>
#include <linux/list_sort.h>
#include "i915_drv.h"
#include "gvt.h"
struct mmio_diff_param {
struct intel_vgpu *vgpu;
int total;
int diff;
struct list_head diff_mmio_list;
};
struct diff_mmio {
struct list_head node;
u32 offset;
u32 preg;
u32 vreg;
};
/* Compare two diff_mmio items. */
static int mmio_offset_compare(void *priv,
struct list_head *a, struct list_head *b)
{
struct diff_mmio *ma;
struct diff_mmio *mb;
ma = container_of(a, struct diff_mmio, node);
mb = container_of(b, struct diff_mmio, node);
if (ma->offset < mb->offset)
return -1;
else if (ma->offset > mb->offset)
return 1;
return 0;
}
static inline int mmio_diff_handler(struct intel_gvt *gvt,
u32 offset, void *data)
{
struct drm_i915_private *dev_priv = gvt->dev_priv;
struct mmio_diff_param *param = data;
struct diff_mmio *node;
u32 preg, vreg;
preg = I915_READ_NOTRACE(_MMIO(offset));
vreg = vgpu_vreg(param->vgpu, offset);
if (preg != vreg) {
node = kmalloc(sizeof(*node), GFP_KERNEL);
if (!node)
return -ENOMEM;
node->offset = offset;
node->preg = preg;
node->vreg = vreg;
list_add(&node->node, &param->diff_mmio_list);
param->diff++;
}
param->total++;
return 0;
}
/* Show the all the different values of tracked mmio. */
static int vgpu_mmio_diff_show(struct seq_file *s, void *unused)
{
struct intel_vgpu *vgpu = s->private;
struct intel_gvt *gvt = vgpu->gvt;
struct mmio_diff_param param = {
.vgpu = vgpu,
.total = 0,
.diff = 0,
};
struct diff_mmio *node, *next;
INIT_LIST_HEAD(&param.diff_mmio_list);
mutex_lock(&gvt->lock);
spin_lock_bh(&gvt->scheduler.mmio_context_lock);
mmio_hw_access_pre(gvt->dev_priv);
/* Recognize all the diff mmios to list. */
intel_gvt_for_each_tracked_mmio(gvt, mmio_diff_handler, &param);
mmio_hw_access_post(gvt->dev_priv);
spin_unlock_bh(&gvt->scheduler.mmio_context_lock);
mutex_unlock(&gvt->lock);
/* In an ascending order by mmio offset. */
list_sort(NULL, &param.diff_mmio_list, mmio_offset_compare);
seq_printf(s, "%-8s %-8s %-8s %-8s\n", "Offset", "HW", "vGPU", "Diff");
list_for_each_entry_safe(node, next, &param.diff_mmio_list, node) {
u32 diff = node->preg ^ node->vreg;
seq_printf(s, "%08x %08x %08x %*pbl\n",
node->offset, node->preg, node->vreg,
32, &diff);
list_del(&node->node);
kfree(node);
}
seq_printf(s, "Total: %d, Diff: %d\n", param.total, param.diff);
return 0;
}
static int vgpu_mmio_diff_open(struct inode *inode, struct file *file)
{
return single_open(file, vgpu_mmio_diff_show, inode->i_private);
}
static const struct file_operations vgpu_mmio_diff_fops = {
.open = vgpu_mmio_diff_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
/**
* intel_gvt_debugfs_add_vgpu - register debugfs entries for a vGPU
* @vgpu: a vGPU
*
* Returns:
* Zero on success, negative error code if failed.
*/
int intel_gvt_debugfs_add_vgpu(struct intel_vgpu *vgpu)
{
struct dentry *ent;
char name[10] = "";
sprintf(name, "vgpu%d", vgpu->id);
vgpu->debugfs = debugfs_create_dir(name, vgpu->gvt->debugfs_root);
if (!vgpu->debugfs)
return -ENOMEM;
ent = debugfs_create_bool("active", 0444, vgpu->debugfs,
&vgpu->active);
if (!ent)
return -ENOMEM;
ent = debugfs_create_file("mmio_diff", 0444, vgpu->debugfs,
vgpu, &vgpu_mmio_diff_fops);
if (!ent)
return -ENOMEM;
return 0;
}
/**
* intel_gvt_debugfs_remove_vgpu - remove debugfs entries of a vGPU
* @vgpu: a vGPU
*/
void intel_gvt_debugfs_remove_vgpu(struct intel_vgpu *vgpu)
{
debugfs_remove_recursive(vgpu->debugfs);
vgpu->debugfs = NULL;
}
/**
* intel_gvt_debugfs_init - register gvt debugfs root entry
* @gvt: GVT device
*
* Returns:
* zero on success, negative if failed.
*/
int intel_gvt_debugfs_init(struct intel_gvt *gvt)
{
struct drm_minor *minor = gvt->dev_priv->drm.primary;
struct dentry *ent;
gvt->debugfs_root = debugfs_create_dir("gvt", minor->debugfs_root);
if (!gvt->debugfs_root) {
gvt_err("Cannot create debugfs dir\n");
return -ENOMEM;
}
ent = debugfs_create_ulong("num_tracked_mmio", 0444, gvt->debugfs_root,
&gvt->mmio.num_tracked_mmio);
if (!ent)
return -ENOMEM;
return 0;
}
/**
* intel_gvt_debugfs_clean - remove debugfs entries
* @gvt: GVT device
*/
void intel_gvt_debugfs_clean(struct intel_gvt *gvt)
{
debugfs_remove_recursive(gvt->debugfs_root);
gvt->debugfs_root = NULL;
}
This diff is collapsed.
......@@ -36,10 +36,6 @@
#define _GVT_EXECLIST_H_
struct execlist_ctx_descriptor_format {
union {
u32 udw;
u32 context_id;
};
union {
u32 ldw;
struct {
......@@ -54,6 +50,10 @@ struct execlist_ctx_descriptor_format {
u32 lrca : 20;
};
};
union {
u32 udw;
u32 context_id;
};
};
struct execlist_status_format {
......
......@@ -66,20 +66,23 @@ static struct bin_attribute firmware_attr = {
.mmap = NULL,
};
static int expose_firmware_sysfs(struct intel_gvt *gvt)
static int mmio_snapshot_handler(struct intel_gvt *gvt, u32 offset, void *data)
{
struct drm_i915_private *dev_priv = gvt->dev_priv;
*(u32 *)(data + offset) = I915_READ_NOTRACE(_MMIO(offset));
return 0;
}
static int expose_firmware_sysfs(struct intel_gvt *gvt)
{
struct intel_gvt_device_info *info = &gvt->device_info;
struct pci_dev *pdev = gvt->dev_priv->drm.pdev;
struct intel_gvt_mmio_info *e;
struct gvt_mmio_block *block = gvt->mmio.mmio_block;
int num = gvt->mmio.num_mmio_block;
struct gvt_firmware_header *h;
void *firmware;
void *p;
unsigned long size, crc32_start;
int i, j;
int ret;
int i, ret;
size = sizeof(*h) + info->mmio_size + info->cfg_space_size;
firmware = vzalloc(size);
......@@ -104,15 +107,8 @@ static int expose_firmware_sysfs(struct intel_gvt *gvt)
p = firmware + h->mmio_offset;
hash_for_each(gvt->mmio.mmio_info_table, i, e, node)
*(u32 *)(p + e->offset) = I915_READ_NOTRACE(_MMIO(e->offset));
for (i = 0; i < num; i++, block++) {
for (j = 0; j < block->size; j += 4)
*(u32 *)(p + INTEL_GVT_MMIO_OFFSET(block->offset) + j) =
I915_READ_NOTRACE(_MMIO(INTEL_GVT_MMIO_OFFSET(
block->offset) + j));
}
/* Take a snapshot of hw mmio registers. */
intel_gvt_for_each_tracked_mmio(gvt, mmio_snapshot_handler, p);
memcpy(gvt->firmware.mmio, p, info->mmio_size);
......
This diff is collapsed.
......@@ -34,9 +34,8 @@
#ifndef _GVT_GTT_H_
#define _GVT_GTT_H_
#define GTT_PAGE_SHIFT 12
#define GTT_PAGE_SIZE (1UL << GTT_PAGE_SHIFT)
#define GTT_PAGE_MASK (~(GTT_PAGE_SIZE-1))
#define I915_GTT_PAGE_SHIFT 12
#define I915_GTT_PAGE_MASK (~(I915_GTT_PAGE_SIZE - 1))
struct intel_vgpu_mm;
......@@ -63,6 +62,7 @@ struct intel_gvt_gtt_pte_ops {
struct intel_vgpu *vgpu);
bool (*test_present)(struct intel_gvt_gtt_entry *e);
void (*clear_present)(struct intel_gvt_gtt_entry *e);
void (*set_present)(struct intel_gvt_gtt_entry *e);
bool (*test_pse)(struct intel_gvt_gtt_entry *e);
void (*set_pfn)(struct intel_gvt_gtt_entry *e, unsigned long pfn);
unsigned long (*get_pfn)(struct intel_gvt_gtt_entry *e);
......@@ -86,8 +86,8 @@ struct intel_gvt_gtt {
struct list_head oos_page_free_list_head;
struct list_head mm_lru_list_head;
struct page *scratch_ggtt_page;
unsigned long scratch_ggtt_mfn;
struct page *scratch_page;
unsigned long scratch_mfn;
};
enum {
......@@ -193,18 +193,16 @@ struct intel_vgpu_scratch_pt {
unsigned long page_mfn;
};
struct intel_vgpu_gtt {
struct intel_vgpu_mm *ggtt_mm;
unsigned long active_ppgtt_mm_bitmap;
struct list_head mm_list_head;
DECLARE_HASHTABLE(shadow_page_hash_table, INTEL_GVT_GTT_HASH_BITS);
DECLARE_HASHTABLE(guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS);
atomic_t n_write_protected_guest_page;
DECLARE_HASHTABLE(tracked_guest_page_hash_table, INTEL_GVT_GTT_HASH_BITS);
atomic_t n_tracked_guest_page;
struct list_head oos_page_list_head;
struct list_head post_shadow_list_head;
struct intel_vgpu_scratch_pt scratch_pt[GTT_TYPE_MAX];
};
extern int intel_vgpu_init_gtt(struct intel_vgpu *vgpu);
......@@ -228,12 +226,16 @@ struct intel_vgpu_shadow_page {
unsigned long mfn;
};
struct intel_vgpu_guest_page {
struct intel_vgpu_page_track {
struct hlist_node node;
bool writeprotection;
bool tracked;
unsigned long gfn;
int (*handler)(void *, u64, void *, int);
void *data;
};
struct intel_vgpu_guest_page {
struct intel_vgpu_page_track track;
unsigned long write_cnt;
struct intel_vgpu_oos_page *oos_page;
};
......@@ -243,7 +245,7 @@ struct intel_vgpu_oos_page {
struct list_head list;
struct list_head vm_list;
int id;
unsigned char mem[GTT_PAGE_SIZE];
unsigned char mem[I915_GTT_PAGE_SIZE];
};
#define GTT_ENTRY_NUM_IN_ONE_PAGE 512
......@@ -258,22 +260,16 @@ struct intel_vgpu_ppgtt_spt {
struct list_head post_shadow_list;
};
int intel_vgpu_init_guest_page(struct intel_vgpu *vgpu,
struct intel_vgpu_guest_page *guest_page,
int intel_vgpu_init_page_track(struct intel_vgpu *vgpu,
struct intel_vgpu_page_track *t,
unsigned long gfn,
int (*handler)(void *gp, u64, void *, int),
void *data);
void intel_vgpu_clean_guest_page(struct intel_vgpu *vgpu,
struct intel_vgpu_guest_page *guest_page);
int intel_vgpu_set_guest_page_writeprotection(struct intel_vgpu *vgpu,
struct intel_vgpu_guest_page *guest_page);
void intel_vgpu_clear_guest_page_writeprotection(struct intel_vgpu *vgpu,
struct intel_vgpu_guest_page *guest_page);
void intel_vgpu_clean_page_track(struct intel_vgpu *vgpu,
struct intel_vgpu_page_track *t);
struct intel_vgpu_guest_page *intel_vgpu_find_guest_page(
struct intel_vgpu_page_track *intel_vgpu_find_tracked_page(
struct intel_vgpu *vgpu, unsigned long gfn);
int intel_vgpu_sync_oos_pages(struct intel_vgpu *vgpu);
......
......@@ -36,6 +36,8 @@
#include "i915_drv.h"
#include "gvt.h"
#include <linux/vfio.h>
#include <linux/mdev.h>
struct intel_gvt_host intel_gvt_host;
......@@ -44,6 +46,129 @@ static const char * const supported_hypervisors[] = {
[INTEL_GVT_HYPERVISOR_KVM] = "KVM",
};
static struct intel_vgpu_type *intel_gvt_find_vgpu_type(struct intel_gvt *gvt,
const char *name)
{
int i;
struct intel_vgpu_type *t;
const char *driver_name = dev_driver_string(
&gvt->dev_priv->drm.pdev->dev);
for (i = 0; i < gvt->num_types; i++) {
t = &gvt->types[i];
if (!strncmp(t->name, name + strlen(driver_name) + 1,
sizeof(t->name)))
return t;
}
return NULL;
}
static ssize_t available_instances_show(struct kobject *kobj,
struct device *dev, char *buf)
{
struct intel_vgpu_type *type;
unsigned int num = 0;
void *gvt = kdev_to_i915(dev)->gvt;
type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj));
if (!type)
num = 0;
else
num = type->avail_instance;
return sprintf(buf, "%u\n", num);
}
static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
char *buf)
{
return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
}
static ssize_t description_show(struct kobject *kobj, struct device *dev,
char *buf)
{
struct intel_vgpu_type *type;
void *gvt = kdev_to_i915(dev)->gvt;
type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj));
if (!type)
return 0;
return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n"
"fence: %d\nresolution: %s\n"
"weight: %d\n",
BYTES_TO_MB(type->low_gm_size),
BYTES_TO_MB(type->high_gm_size),
type->fence, vgpu_edid_str(type->resolution),
type->weight);
}
static MDEV_TYPE_ATTR_RO(available_instances);
static MDEV_TYPE_ATTR_RO(device_api);
static MDEV_TYPE_ATTR_RO(description);
static struct attribute *gvt_type_attrs[] = {
&mdev_type_attr_available_instances.attr,
&mdev_type_attr_device_api.attr,
&mdev_type_attr_description.attr,
NULL,
};
static struct attribute_group *gvt_vgpu_type_groups[] = {
[0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL,
};
static bool intel_get_gvt_attrs(struct attribute ***type_attrs,
struct attribute_group ***intel_vgpu_type_groups)
{
*type_attrs = gvt_type_attrs;
*intel_vgpu_type_groups = gvt_vgpu_type_groups;
return true;
}
static bool intel_gvt_init_vgpu_type_groups(struct intel_gvt *gvt)
{
int i, j;
struct intel_vgpu_type *type;
struct attribute_group *group;
for (i = 0; i < gvt->num_types; i++) {
type = &gvt->types[i];
group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
if (WARN_ON(!group))
goto unwind;
group->name = type->name;
group->attrs = gvt_type_attrs;
gvt_vgpu_type_groups[i] = group;
}
return true;
unwind:
for (j = 0; j < i; j++) {
group = gvt_vgpu_type_groups[j];
kfree(group);
}
return false;
}
static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt)
{
int i;
struct attribute_group *group;
for (i = 0; i < gvt->num_types; i++) {
group = gvt_vgpu_type_groups[i];
gvt_vgpu_type_groups[i] = NULL;
kfree(group);
}
}
static const struct intel_gvt_ops intel_gvt_ops = {
.emulate_cfg_read = intel_vgpu_emulate_cfg_read,
.emulate_cfg_write = intel_vgpu_emulate_cfg_write,
......@@ -54,6 +179,8 @@ static const struct intel_gvt_ops intel_gvt_ops = {
.vgpu_reset = intel_gvt_reset_vgpu,
.vgpu_activate = intel_gvt_activate_vgpu,
.vgpu_deactivate = intel_gvt_deactivate_vgpu,
.gvt_find_vgpu_type = intel_gvt_find_vgpu_type,
.get_gvt_attrs = intel_get_gvt_attrs,
};
/**
......@@ -191,17 +318,18 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
if (WARN_ON(!gvt))
return;
intel_gvt_debugfs_clean(gvt);
clean_service_thread(gvt);
intel_gvt_clean_cmd_parser(gvt);
intel_gvt_clean_sched_policy(gvt);
intel_gvt_clean_workload_scheduler(gvt);
intel_gvt_clean_opregion(gvt);
intel_gvt_clean_gtt(gvt);
intel_gvt_clean_irq(gvt);
intel_gvt_clean_mmio_info(gvt);
intel_gvt_free_firmware(gvt);
intel_gvt_hypervisor_host_exit(&dev_priv->drm.pdev->dev, gvt);
intel_gvt_cleanup_vgpu_type_groups(gvt);
intel_gvt_clean_vgpu_types(gvt);
idr_destroy(&gvt->vgpu_idr);
......@@ -268,13 +396,9 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
if (ret)
goto out_clean_irq;
ret = intel_gvt_init_opregion(gvt);
if (ret)
goto out_clean_gtt;
ret = intel_gvt_init_workload_scheduler(gvt);
if (ret)
goto out_clean_opregion;
goto out_clean_gtt;
ret = intel_gvt_init_sched_policy(gvt);
if (ret)
......@@ -292,6 +416,12 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
if (ret)
goto out_clean_thread;
ret = intel_gvt_init_vgpu_type_groups(gvt);
if (ret == false) {
gvt_err("failed to init vgpu type groups: %d\n", ret);
goto out_clean_types;
}
ret = intel_gvt_hypervisor_host_init(&dev_priv->drm.pdev->dev, gvt,
&intel_gvt_ops);
if (ret) {
......@@ -307,6 +437,10 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
}
gvt->idle_vgpu = vgpu;
ret = intel_gvt_debugfs_init(gvt);
if (ret)
gvt_err("debugfs registeration failed, go on.\n");
gvt_dbg_core("gvt device initialization is done\n");
dev_priv->gvt = gvt;
return 0;
......@@ -321,8 +455,6 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
intel_gvt_clean_sched_policy(gvt);
out_clean_workload_scheduler:
intel_gvt_clean_workload_scheduler(gvt);
out_clean_opregion:
intel_gvt_clean_opregion(gvt);
out_clean_gtt:
intel_gvt_clean_gtt(gvt);
out_clean_irq:
......
......@@ -125,7 +125,6 @@ struct intel_vgpu_irq {
struct intel_vgpu_opregion {
void *va;
u32 gfn[INTEL_GVT_OPREGION_PAGES];
struct page *pages[INTEL_GVT_OPREGION_PAGES];
};
#define vgpu_opregion(vgpu) (&(vgpu->opregion))
......@@ -142,6 +141,33 @@ struct vgpu_sched_ctl {
int weight;
};
enum {
INTEL_VGPU_EXECLIST_SUBMISSION = 1,
INTEL_VGPU_GUC_SUBMISSION,
};
struct intel_vgpu_submission_ops {
const char *name;
int (*init)(struct intel_vgpu *vgpu);
void (*clean)(struct intel_vgpu *vgpu);
void (*reset)(struct intel_vgpu *vgpu, unsigned long engine_mask);
};
struct intel_vgpu_submission {
struct intel_vgpu_execlist execlist[I915_NUM_ENGINES];
struct list_head workload_q_head[I915_NUM_ENGINES];
struct kmem_cache *workloads;
atomic_t running_workload_num;
struct i915_gem_context *shadow_ctx;
DECLARE_BITMAP(shadow_ctx_desc_updated, I915_NUM_ENGINES);
DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES);
void *ring_scan_buffer[I915_NUM_ENGINES];
int ring_scan_buffer_size[I915_NUM_ENGINES];
const struct intel_vgpu_submission_ops *ops;
int virtual_submission_interface;
bool active;
};
struct intel_vgpu {
struct intel_gvt *gvt;
int id;
......@@ -161,16 +187,10 @@ struct intel_vgpu {
struct intel_vgpu_gtt gtt;
struct intel_vgpu_opregion opregion;
struct intel_vgpu_display display;
struct intel_vgpu_execlist execlist[I915_NUM_ENGINES];
struct list_head workload_q_head[I915_NUM_ENGINES];
struct kmem_cache *workloads;
atomic_t running_workload_num;
/* 1/2K for each reserve ring buffer */
void *reserve_ring_buffer_va[I915_NUM_ENGINES];
int reserve_ring_buffer_size[I915_NUM_ENGINES];
DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES);
struct i915_gem_context *shadow_ctx;
DECLARE_BITMAP(shadow_ctx_desc_updated, I915_NUM_ENGINES);
struct intel_vgpu_submission submission;
u32 hws_pga[I915_NUM_ENGINES];
struct dentry *debugfs;
#if IS_ENABLED(CONFIG_DRM_I915_GVT_KVMGT)
struct {
......@@ -190,6 +210,10 @@ struct intel_vgpu {
#endif
};
/* validating GM healthy status*/
#define vgpu_is_vm_unhealthy(ret_val) \
(((ret_val) == -EBADRQC) || ((ret_val) == -EFAULT))
struct intel_gvt_gm {
unsigned long vgpu_allocated_low_gm_size;
unsigned long vgpu_allocated_high_gm_size;
......@@ -231,7 +255,7 @@ struct intel_gvt_mmio {
unsigned int num_mmio_block;
DECLARE_HASHTABLE(mmio_info_table, INTEL_GVT_MMIO_HASH_BITS);
unsigned int num_tracked_mmio;
unsigned long num_tracked_mmio;
};
struct intel_gvt_firmware {
......@@ -240,11 +264,6 @@ struct intel_gvt_firmware {
bool firmware_loaded;
};
struct intel_gvt_opregion {
void *opregion_va;
u32 opregion_pa;
};
#define NR_MAX_INTEL_VGPU_TYPES 20
struct intel_vgpu_type {
char name[16];
......@@ -268,7 +287,6 @@ struct intel_gvt {
struct intel_gvt_firmware firmware;
struct intel_gvt_irq irq;
struct intel_gvt_gtt gtt;
struct intel_gvt_opregion opregion;
struct intel_gvt_workload_scheduler scheduler;
struct notifier_block shadow_ctx_notifier_block[I915_NUM_ENGINES];
DECLARE_HASHTABLE(cmd_table, GVT_CMD_HASH_BITS);
......@@ -279,6 +297,8 @@ struct intel_gvt {
struct task_struct *service_thread;
wait_queue_head_t service_thread_wq;
unsigned long service_request;
struct dentry *debugfs_root;
};
static inline struct intel_gvt *to_gvt(struct drm_i915_private *i915)
......@@ -484,9 +504,6 @@ static inline u64 intel_vgpu_get_bar_gpa(struct intel_vgpu *vgpu, int bar)
PCI_BASE_ADDRESS_MEM_MASK;
}
void intel_gvt_clean_opregion(struct intel_gvt *gvt);
int intel_gvt_init_opregion(struct intel_gvt *gvt);
void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu);
int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa);
......@@ -494,6 +511,7 @@ int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci);
void populate_pvinfo_page(struct intel_vgpu *vgpu);
int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload);
void enter_failsafe_mode(struct intel_vgpu *vgpu, int reason);
struct intel_gvt_ops {
int (*emulate_cfg_read)(struct intel_vgpu *, unsigned int, void *,
......@@ -510,12 +528,17 @@ struct intel_gvt_ops {
void (*vgpu_reset)(struct intel_vgpu *);
void (*vgpu_activate)(struct intel_vgpu *);
void (*vgpu_deactivate)(struct intel_vgpu *);
struct intel_vgpu_type *(*gvt_find_vgpu_type)(struct intel_gvt *gvt,
const char *name);
bool (*get_gvt_attrs)(struct attribute ***type_attrs,
struct attribute_group ***intel_vgpu_type_groups);
};
enum {
GVT_FAILSAFE_UNSUPPORTED_GUEST,
GVT_FAILSAFE_INSUFFICIENT_RESOURCE,
GVT_FAILSAFE_GUEST_ERR,
};
static inline void mmio_hw_access_pre(struct drm_i915_private *dev_priv)
......@@ -591,6 +614,12 @@ static inline bool intel_gvt_mmio_has_mode_mask(
return gvt->mmio.mmio_attribute[offset >> 2] & F_MODE_MASK;
}
int intel_gvt_debugfs_add_vgpu(struct intel_vgpu *vgpu);
void intel_gvt_debugfs_remove_vgpu(struct intel_vgpu *vgpu);
int intel_gvt_debugfs_init(struct intel_gvt *gvt);
void intel_gvt_debugfs_clean(struct intel_gvt *gvt);
#include "trace.h"
#include "mpt.h"
......
......@@ -137,17 +137,26 @@ static int new_mmio_info(struct intel_gvt *gvt,
return 0;
}
static int render_mmio_to_ring_id(struct intel_gvt *gvt, unsigned int reg)
/**
* intel_gvt_render_mmio_to_ring_id - convert a mmio offset into ring id
* @gvt: a GVT device
* @offset: register offset
*
* Returns:
* Ring ID on success, negative error code if failed.
*/
int intel_gvt_render_mmio_to_ring_id(struct intel_gvt *gvt,
unsigned int offset)
{
enum intel_engine_id id;
struct intel_engine_cs *engine;
reg &= ~GENMASK(11, 0);
offset &= ~GENMASK(11, 0);
for_each_engine(engine, gvt->dev_priv, id) {
if (engine->mmio_base == reg)
if (engine->mmio_base == offset)
return id;
}
return -1;
return -ENODEV;
}
#define offset_to_fence_num(offset) \
......@@ -157,7 +166,7 @@ static int render_mmio_to_ring_id(struct intel_gvt *gvt, unsigned int reg)
(num * 8 + i915_mmio_reg_offset(FENCE_REG_GEN6_LO(0)))
static void enter_failsafe_mode(struct intel_vgpu *vgpu, int reason)
void enter_failsafe_mode(struct intel_vgpu *vgpu, int reason)
{
switch (reason) {
case GVT_FAILSAFE_UNSUPPORTED_GUEST:
......@@ -165,6 +174,8 @@ static void enter_failsafe_mode(struct intel_vgpu *vgpu, int reason)
break;
case GVT_FAILSAFE_INSUFFICIENT_RESOURCE:
pr_err("Graphics resource is not enough for the guest\n");
case GVT_FAILSAFE_GUEST_ERR:
pr_err("GVT Internal error for the guest\n");
default:
break;
}
......@@ -1369,6 +1380,34 @@ static int mailbox_write(struct intel_vgpu *vgpu, unsigned int offset,
return intel_vgpu_default_mmio_write(vgpu, offset, &value, bytes);
}
static int hws_pga_write(struct intel_vgpu *vgpu, unsigned int offset,
void *p_data, unsigned int bytes)
{
u32 value = *(u32 *)p_data;
int ring_id = intel_gvt_render_mmio_to_ring_id(vgpu->gvt, offset);
if (!intel_gvt_ggtt_validate_range(vgpu, value, I915_GTT_PAGE_SIZE)) {
gvt_vgpu_err("VM(%d) write invalid HWSP address, reg:0x%x, value:0x%x\n",
vgpu->id, offset, value);
return -EINVAL;
}
/*
* Need to emulate all the HWSP register write to ensure host can
* update the VM CSB status correctly. Here listed registers can
* support BDW, SKL or other platforms with same HWSP registers.
*/
if (unlikely(ring_id < 0 || ring_id > I915_NUM_ENGINES)) {
gvt_vgpu_err("VM(%d) access unknown hardware status page register:0x%x\n",
vgpu->id, offset);
return -EINVAL;
}
vgpu->hws_pga[ring_id] = value;
gvt_dbg_mmio("VM(%d) write: 0x%x to HWSP: 0x%x\n",
vgpu->id, value, offset);
return intel_vgpu_default_mmio_write(vgpu, offset, &value, bytes);
}
static int skl_power_well_ctl_write(struct intel_vgpu *vgpu,
unsigned int offset, void *p_data, unsigned int bytes)
{
......@@ -1432,18 +1471,36 @@ static int skl_lcpll_write(struct intel_vgpu *vgpu, unsigned int offset,
static int mmio_read_from_hw(struct intel_vgpu *vgpu,
unsigned int offset, void *p_data, unsigned int bytes)
{
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
struct intel_gvt *gvt = vgpu->gvt;
struct drm_i915_private *dev_priv = gvt->dev_priv;
int ring_id;
u32 ring_base;
ring_id = intel_gvt_render_mmio_to_ring_id(gvt, offset);
/**
* Read HW reg in following case
* a. the offset isn't a ring mmio
* b. the offset's ring is running on hw.
* c. the offset is ring time stamp mmio
*/
if (ring_id >= 0)
ring_base = dev_priv->engine[ring_id]->mmio_base;
if (ring_id < 0 || vgpu == gvt->scheduler.engine_owner[ring_id] ||
offset == i915_mmio_reg_offset(RING_TIMESTAMP(ring_base)) ||
offset == i915_mmio_reg_offset(RING_TIMESTAMP_UDW(ring_base))) {
mmio_hw_access_pre(dev_priv);
vgpu_vreg(vgpu, offset) = I915_READ(_MMIO(offset));
mmio_hw_access_post(dev_priv);
}
mmio_hw_access_pre(dev_priv);
vgpu_vreg(vgpu, offset) = I915_READ(_MMIO(offset));
mmio_hw_access_post(dev_priv);
return intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes);
}
static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
void *p_data, unsigned int bytes)
{
int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset);
int ring_id = intel_gvt_render_mmio_to_ring_id(vgpu->gvt, offset);
struct intel_vgpu_execlist *execlist;
u32 data = *(u32 *)p_data;
int ret = 0;
......@@ -1451,9 +1508,9 @@ static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
if (WARN_ON(ring_id < 0 || ring_id > I915_NUM_ENGINES - 1))
return -EINVAL;
execlist = &vgpu->execlist[ring_id];
execlist = &vgpu->submission.execlist[ring_id];
execlist->elsp_dwords.data[execlist->elsp_dwords.index] = data;
execlist->elsp_dwords.data[3 - execlist->elsp_dwords.index] = data;
if (execlist->elsp_dwords.index == 3) {
ret = intel_vgpu_submit_execlist(vgpu, ring_id);
if(ret)
......@@ -1469,9 +1526,11 @@ static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
void *p_data, unsigned int bytes)
{
struct intel_vgpu_submission *s = &vgpu->submission;
u32 data = *(u32 *)p_data;
int ring_id = render_mmio_to_ring_id(vgpu->gvt, offset);
int ring_id = intel_gvt_render_mmio_to_ring_id(vgpu->gvt, offset);
bool enable_execlist;
int ret;
write_vreg(vgpu, offset, p_data, bytes);
......@@ -1493,8 +1552,18 @@ static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset,
(enable_execlist ? "enabling" : "disabling"),
ring_id);
if (enable_execlist)
intel_vgpu_start_schedule(vgpu);
if (!enable_execlist)
return 0;
if (s->active)
return 0;
ret = intel_vgpu_select_submission_ops(vgpu,
INTEL_VGPU_EXECLIST_SUBMISSION);
if (ret)
return ret;
intel_vgpu_start_schedule(vgpu);
}
return 0;
}
......@@ -1526,7 +1595,7 @@ static int gvt_reg_tlb_control_handler(struct intel_vgpu *vgpu,
default:
return -EINVAL;
}
set_bit(id, (void *)vgpu->tlb_handle_pending);
set_bit(id, (void *)vgpu->submission.tlb_handle_pending);
return 0;
}
......@@ -2512,7 +2581,7 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)
MMIO_RING_F(RING_REG, 32, 0, 0, 0, D_BDW_PLUS, NULL, NULL);
#undef RING_REG
MMIO_RING_GM_RDR(RING_HWS_PGA, D_BDW_PLUS, NULL, NULL);
MMIO_RING_GM_RDR(RING_HWS_PGA, D_BDW_PLUS, NULL, hws_pga_write);
MMIO_DFH(HDC_CHICKEN0, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
......@@ -2914,14 +2983,46 @@ int intel_gvt_setup_mmio_info(struct intel_gvt *gvt)
gvt->mmio.mmio_block = mmio_blocks;
gvt->mmio.num_mmio_block = ARRAY_SIZE(mmio_blocks);
gvt_dbg_mmio("traced %u virtual mmio registers\n",
gvt->mmio.num_tracked_mmio);
return 0;
err:
intel_gvt_clean_mmio_info(gvt);
return ret;
}
/**
* intel_gvt_for_each_tracked_mmio - iterate each tracked mmio
* @gvt: a GVT device
* @handler: the handler
* @data: private data given to handler
*
* Returns:
* Zero on success, negative error code if failed.
*/
int intel_gvt_for_each_tracked_mmio(struct intel_gvt *gvt,
int (*handler)(struct intel_gvt *gvt, u32 offset, void *data),
void *data)
{
struct gvt_mmio_block *block = gvt->mmio.mmio_block;
struct intel_gvt_mmio_info *e;
int i, j, ret;
hash_for_each(gvt->mmio.mmio_info_table, i, e, node) {
ret = handler(gvt, e->offset, data);
if (ret)
return ret;
}
for (i = 0; i < gvt->mmio.num_mmio_block; i++, block++) {
for (j = 0; j < block->size; j += 4) {
ret = handler(gvt,
INTEL_GVT_MMIO_OFFSET(block->offset) + j,
data);
if (ret)
return ret;
}
}
return 0;
}
/**
* intel_vgpu_default_mmio_read - default MMIO read handler
......
......@@ -248,120 +248,6 @@ static void gvt_cache_destroy(struct intel_vgpu *vgpu)
}
}
static struct intel_vgpu_type *intel_gvt_find_vgpu_type(struct intel_gvt *gvt,
const char *name)
{
int i;
struct intel_vgpu_type *t;
const char *driver_name = dev_driver_string(
&gvt->dev_priv->drm.pdev->dev);
for (i = 0; i < gvt->num_types; i++) {
t = &gvt->types[i];
if (!strncmp(t->name, name + strlen(driver_name) + 1,
sizeof(t->name)))
return t;
}
return NULL;
}
static ssize_t available_instances_show(struct kobject *kobj,
struct device *dev, char *buf)
{
struct intel_vgpu_type *type;
unsigned int num = 0;
void *gvt = kdev_to_i915(dev)->gvt;
type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj));
if (!type)
num = 0;
else
num = type->avail_instance;
return sprintf(buf, "%u\n", num);
}
static ssize_t device_api_show(struct kobject *kobj, struct device *dev,
char *buf)
{
return sprintf(buf, "%s\n", VFIO_DEVICE_API_PCI_STRING);
}
static ssize_t description_show(struct kobject *kobj, struct device *dev,
char *buf)
{
struct intel_vgpu_type *type;
void *gvt = kdev_to_i915(dev)->gvt;
type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj));
if (!type)
return 0;
return sprintf(buf, "low_gm_size: %dMB\nhigh_gm_size: %dMB\n"
"fence: %d\nresolution: %s\n"
"weight: %d\n",
BYTES_TO_MB(type->low_gm_size),
BYTES_TO_MB(type->high_gm_size),
type->fence, vgpu_edid_str(type->resolution),
type->weight);
}
static MDEV_TYPE_ATTR_RO(available_instances);
static MDEV_TYPE_ATTR_RO(device_api);
static MDEV_TYPE_ATTR_RO(description);
static struct attribute *type_attrs[] = {
&mdev_type_attr_available_instances.attr,
&mdev_type_attr_device_api.attr,
&mdev_type_attr_description.attr,
NULL,
};
static struct attribute_group *intel_vgpu_type_groups[] = {
[0 ... NR_MAX_INTEL_VGPU_TYPES - 1] = NULL,
};
static bool intel_gvt_init_vgpu_type_groups(struct intel_gvt *gvt)
{
int i, j;
struct intel_vgpu_type *type;
struct attribute_group *group;
for (i = 0; i < gvt->num_types; i++) {
type = &gvt->types[i];
group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
if (WARN_ON(!group))
goto unwind;
group->name = type->name;
group->attrs = type_attrs;
intel_vgpu_type_groups[i] = group;
}
return true;
unwind:
for (j = 0; j < i; j++) {
group = intel_vgpu_type_groups[j];
kfree(group);
}
return false;
}
static void intel_gvt_cleanup_vgpu_type_groups(struct intel_gvt *gvt)
{
int i;
struct attribute_group *group;
for (i = 0; i < gvt->num_types; i++) {
group = intel_vgpu_type_groups[i];
kfree(group);
}
}
static void kvmgt_protect_table_init(struct kvmgt_guest_info *info)
{
hash_init(info->ptable);
......@@ -441,7 +327,7 @@ static int intel_vgpu_create(struct kobject *kobj, struct mdev_device *mdev)
pdev = mdev_parent_dev(mdev);
gvt = kdev_to_i915(pdev)->gvt;
type = intel_gvt_find_vgpu_type(gvt, kobject_name(kobj));
type = intel_gvt_ops->gvt_find_vgpu_type(gvt, kobject_name(kobj));
if (!type) {
gvt_vgpu_err("failed to find type %s to create\n",
kobject_name(kobj));
......@@ -1188,7 +1074,7 @@ hw_id_show(struct device *dev, struct device_attribute *attr,
struct intel_vgpu *vgpu = (struct intel_vgpu *)
mdev_get_drvdata(mdev);
return sprintf(buf, "%u\n",
vgpu->shadow_ctx->hw_id);
vgpu->submission.shadow_ctx->hw_id);
}
return sprintf(buf, "\n");
}
......@@ -1212,8 +1098,7 @@ static const struct attribute_group *intel_vgpu_groups[] = {
NULL,
};
static const struct mdev_parent_ops intel_vgpu_ops = {
.supported_type_groups = intel_vgpu_type_groups,
static struct mdev_parent_ops intel_vgpu_ops = {
.mdev_attr_groups = intel_vgpu_groups,
.create = intel_vgpu_create,
.remove = intel_vgpu_remove,
......@@ -1229,17 +1114,20 @@ static const struct mdev_parent_ops intel_vgpu_ops = {
static int kvmgt_host_init(struct device *dev, void *gvt, const void *ops)
{
if (!intel_gvt_init_vgpu_type_groups(gvt))
return -EFAULT;
struct attribute **kvm_type_attrs;
struct attribute_group **kvm_vgpu_type_groups;
intel_gvt_ops = ops;
if (!intel_gvt_ops->get_gvt_attrs(&kvm_type_attrs,
&kvm_vgpu_type_groups))
return -EFAULT;
intel_vgpu_ops.supported_type_groups = kvm_vgpu_type_groups;
return mdev_register_device(dev, &intel_vgpu_ops);
}
static void kvmgt_host_exit(struct device *dev, void *gvt)
{
intel_gvt_cleanup_vgpu_type_groups(gvt);
mdev_unregister_device(dev);
}
......
......@@ -117,18 +117,18 @@ static void failsafe_emulate_mmio_rw(struct intel_vgpu *vgpu, uint64_t pa,
else
memcpy(pt, p_data, bytes);
} else if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) {
struct intel_vgpu_guest_page *gp;
} else if (atomic_read(&vgpu->gtt.n_tracked_guest_page)) {
struct intel_vgpu_page_track *t;
/* Since we enter the failsafe mode early during guest boot,
* guest may not have chance to set up its ppgtt table, so
* there should not be any wp pages for guest. Keep the wp
* related code here in case we need to handle it in furture.
*/
gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT);
if (gp) {
t = intel_vgpu_find_tracked_page(vgpu, pa >> PAGE_SHIFT);
if (t) {
/* remove write protection to prevent furture traps */
intel_vgpu_clean_guest_page(vgpu, gp);
intel_vgpu_clean_page_track(vgpu, t);
if (read)
intel_gvt_hypervisor_read_gpa(vgpu, pa,
p_data, bytes);
......@@ -170,17 +170,17 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa,
return ret;
}
if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) {
struct intel_vgpu_guest_page *gp;
if (atomic_read(&vgpu->gtt.n_tracked_guest_page)) {
struct intel_vgpu_page_track *t;
gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT);
if (gp) {
t = intel_vgpu_find_tracked_page(vgpu, pa >> PAGE_SHIFT);
if (t) {
ret = intel_gvt_hypervisor_read_gpa(vgpu, pa,
p_data, bytes);
if (ret) {
gvt_vgpu_err("guest page read error %d, "
"gfn 0x%lx, pa 0x%llx, var 0x%x, len %d\n",
ret, gp->gfn, pa, *(u32 *)p_data,
ret, t->gfn, pa, *(u32 *)p_data,
bytes);
}
mutex_unlock(&gvt->lock);
......@@ -267,17 +267,17 @@ int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa,
return ret;
}
if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) {
struct intel_vgpu_guest_page *gp;
if (atomic_read(&vgpu->gtt.n_tracked_guest_page)) {
struct intel_vgpu_page_track *t;
gp = intel_vgpu_find_guest_page(vgpu, pa >> PAGE_SHIFT);
if (gp) {
ret = gp->handler(gp, pa, p_data, bytes);
t = intel_vgpu_find_tracked_page(vgpu, pa >> PAGE_SHIFT);
if (t) {
ret = t->handler(t, pa, p_data, bytes);
if (ret) {
gvt_err("guest page write error %d, "
"gfn 0x%lx, pa 0x%llx, "
"var 0x%x, len %d\n",
ret, gp->gfn, pa,
ret, t->gfn, pa,
*(u32 *)p_data, bytes);
}
mutex_unlock(&gvt->lock);
......
......@@ -65,11 +65,17 @@ struct intel_gvt_mmio_info {
struct hlist_node node;
};
int intel_gvt_render_mmio_to_ring_id(struct intel_gvt *gvt,
unsigned int reg);
unsigned long intel_gvt_get_device_type(struct intel_gvt *gvt);
bool intel_gvt_match_device(struct intel_gvt *gvt, unsigned long device);
int intel_gvt_setup_mmio_info(struct intel_gvt *gvt);
void intel_gvt_clean_mmio_info(struct intel_gvt *gvt);
int intel_gvt_for_each_tracked_mmio(struct intel_gvt *gvt,
int (*handler)(struct intel_gvt *gvt, u32 offset, void *data),
void *data);
#define INTEL_GVT_MMIO_OFFSET(reg) ({ \
typeof(reg) __reg = reg; \
......
......@@ -154,51 +154,53 @@ static inline unsigned long intel_gvt_hypervisor_virt_to_mfn(void *p)
}
/**
* intel_gvt_hypervisor_set_wp_page - set a guest page to write-protected
* intel_gvt_hypervisor_enable - set a guest page to write-protected
* @vgpu: a vGPU
* @p: intel_vgpu_guest_page
* @t: page track data structure
*
* Returns:
* Zero on success, negative error code if failed.
*/
static inline int intel_gvt_hypervisor_set_wp_page(struct intel_vgpu *vgpu,
struct intel_vgpu_guest_page *p)
static inline int intel_gvt_hypervisor_enable_page_track(
struct intel_vgpu *vgpu,
struct intel_vgpu_page_track *t)
{
int ret;
if (p->writeprotection)
if (t->tracked)
return 0;
ret = intel_gvt_host.mpt->set_wp_page(vgpu->handle, p->gfn);
ret = intel_gvt_host.mpt->set_wp_page(vgpu->handle, t->gfn);
if (ret)
return ret;
p->writeprotection = true;
atomic_inc(&vgpu->gtt.n_write_protected_guest_page);
t->tracked = true;
atomic_inc(&vgpu->gtt.n_tracked_guest_page);
return 0;
}
/**
* intel_gvt_hypervisor_unset_wp_page - remove the write-protection of a
* intel_gvt_hypervisor_disable_page_track - remove the write-protection of a
* guest page
* @vgpu: a vGPU
* @p: intel_vgpu_guest_page
* @t: page track data structure
*
* Returns:
* Zero on success, negative error code if failed.
*/
static inline int intel_gvt_hypervisor_unset_wp_page(struct intel_vgpu *vgpu,
struct intel_vgpu_guest_page *p)
static inline int intel_gvt_hypervisor_disable_page_track(
struct intel_vgpu *vgpu,
struct intel_vgpu_page_track *t)
{
int ret;
if (!p->writeprotection)
if (!t->tracked)
return 0;
ret = intel_gvt_host.mpt->unset_wp_page(vgpu->handle, p->gfn);
ret = intel_gvt_host.mpt->unset_wp_page(vgpu->handle, t->gfn);
if (ret)
return ret;
p->writeprotection = false;
atomic_dec(&vgpu->gtt.n_write_protected_guest_page);
t->tracked = false;
atomic_dec(&vgpu->gtt.n_tracked_guest_page);
return 0;
}
......
......@@ -25,36 +25,247 @@
#include "i915_drv.h"
#include "gvt.h"
static int init_vgpu_opregion(struct intel_vgpu *vgpu, u32 gpa)
/*
* Note: Only for GVT-g virtual VBT generation, other usage must
* not do like this.
*/
#define _INTEL_BIOS_PRIVATE
#include "intel_vbt_defs.h"
#define OPREGION_SIGNATURE "IntelGraphicsMem"
#define MBOX_VBT (1<<3)
/* device handle */
#define DEVICE_TYPE_CRT 0x01
#define DEVICE_TYPE_EFP1 0x04
#define DEVICE_TYPE_EFP2 0x40
#define DEVICE_TYPE_EFP3 0x20
#define DEVICE_TYPE_EFP4 0x10
#define DEV_SIZE 38
struct opregion_header {
u8 signature[16];
u32 size;
u32 opregion_ver;
u8 bios_ver[32];
u8 vbios_ver[16];
u8 driver_ver[16];
u32 mboxes;
u32 driver_model;
u32 pcon;
u8 dver[32];
u8 rsvd[124];
} __packed;
struct bdb_data_header {
u8 id;
u16 size; /* data size */
} __packed;
struct efp_child_device_config {
u16 handle;
u16 device_type;
u16 device_class;
u8 i2c_speed;
u8 dp_onboard_redriver; /* 158 */
u8 dp_ondock_redriver; /* 158 */
u8 hdmi_level_shifter_value:4; /* 169 */
u8 hdmi_max_data_rate:4; /* 204 */
u16 dtd_buf_ptr; /* 161 */
u8 edidless_efp:1; /* 161 */
u8 compression_enable:1; /* 198 */
u8 compression_method:1; /* 198 */
u8 ganged_edp:1; /* 202 */
u8 skip0:4;
u8 compression_structure_index:4; /* 198 */
u8 skip1:4;
u8 slave_port; /* 202 */
u8 skip2;
u8 dvo_port;
u8 i2c_pin; /* for add-in card */
u8 slave_addr; /* for add-in card */
u8 ddc_pin;
u16 edid_ptr;
u8 dvo_config;
u8 efp_docked_port:1; /* 158 */
u8 lane_reversal:1; /* 184 */
u8 onboard_lspcon:1; /* 192 */
u8 iboost_enable:1; /* 196 */
u8 hpd_invert:1; /* BXT 196 */
u8 slip3:3;
u8 hdmi_compat:1;
u8 dp_compat:1;
u8 tmds_compat:1;
u8 skip4:5;
u8 aux_channel;
u8 dongle_detect;
u8 pipe_cap:2;
u8 sdvo_stall:1; /* 158 */
u8 hpd_status:2;
u8 integrated_encoder:1;
u8 skip5:2;
u8 dvo_wiring;
u8 mipi_bridge_type; /* 171 */
u16 device_class_ext;
u8 dvo_function;
u8 dp_usb_type_c:1; /* 195 */
u8 skip6:7;
u8 dp_usb_type_c_2x_gpio_index; /* 195 */
u16 dp_usb_type_c_2x_gpio_pin; /* 195 */
u8 iboost_dp:4; /* 196 */
u8 iboost_hdmi:4; /* 196 */
} __packed;
struct vbt {
/* header->bdb_offset point to bdb_header offset */
struct vbt_header header;
struct bdb_header bdb_header;
struct bdb_data_header general_features_header;
struct bdb_general_features general_features;
struct bdb_data_header general_definitions_header;
struct bdb_general_definitions general_definitions;
struct efp_child_device_config child0;
struct efp_child_device_config child1;
struct efp_child_device_config child2;
struct efp_child_device_config child3;
struct bdb_data_header driver_features_header;
struct bdb_driver_features driver_features;
};
static void virt_vbt_generation(struct vbt *v)
{
u8 *buf;
int i;
int num_child;
memset(v, 0, sizeof(struct vbt));
v->header.signature[0] = '$';
v->header.signature[1] = 'V';
v->header.signature[2] = 'B';
v->header.signature[3] = 'T';
/* there's features depending on version! */
v->header.version = 155;
v->header.header_size = sizeof(v->header);
v->header.vbt_size = sizeof(struct vbt) - sizeof(v->header);
v->header.bdb_offset = offsetof(struct vbt, bdb_header);
strcpy(&v->bdb_header.signature[0], "BIOS_DATA_BLOCK");
v->bdb_header.version = 186; /* child_dev_size = 38 */
v->bdb_header.header_size = sizeof(v->bdb_header);
v->bdb_header.bdb_size = sizeof(struct vbt) - sizeof(struct vbt_header)
- sizeof(struct bdb_header);
/* general features */
v->general_features_header.id = BDB_GENERAL_FEATURES;
v->general_features_header.size = sizeof(struct bdb_general_features);
v->general_features.int_crt_support = 0;
v->general_features.int_tv_support = 0;
/* child device */
num_child = 4; /* each port has one child */
v->general_definitions_header.id = BDB_GENERAL_DEFINITIONS;
/* size will include child devices */
v->general_definitions_header.size =
sizeof(struct bdb_general_definitions) + num_child * DEV_SIZE;
v->general_definitions.child_dev_size = DEV_SIZE;
/* portA */
v->child0.handle = DEVICE_TYPE_EFP1;
v->child0.device_type = DEVICE_TYPE_DP;
v->child0.dvo_port = DVO_PORT_DPA;
v->child0.aux_channel = DP_AUX_A;
v->child0.dp_compat = true;
v->child0.integrated_encoder = true;
/* portB */
v->child1.handle = DEVICE_TYPE_EFP2;
v->child1.device_type = DEVICE_TYPE_DP;
v->child1.dvo_port = DVO_PORT_DPB;
v->child1.aux_channel = DP_AUX_B;
v->child1.dp_compat = true;
v->child1.integrated_encoder = true;
/* portC */
v->child2.handle = DEVICE_TYPE_EFP3;
v->child2.device_type = DEVICE_TYPE_DP;
v->child2.dvo_port = DVO_PORT_DPC;
v->child2.aux_channel = DP_AUX_C;
v->child2.dp_compat = true;
v->child2.integrated_encoder = true;
/* portD */
v->child3.handle = DEVICE_TYPE_EFP4;
v->child3.device_type = DEVICE_TYPE_DP;
v->child3.dvo_port = DVO_PORT_DPD;
v->child3.aux_channel = DP_AUX_D;
v->child3.dp_compat = true;
v->child3.integrated_encoder = true;
/* driver features */
v->driver_features_header.id = BDB_DRIVER_FEATURES;
v->driver_features_header.size = sizeof(struct bdb_driver_features);
v->driver_features.lvds_config = BDB_DRIVER_FEATURE_NO_LVDS;
}
if (WARN((vgpu_opregion(vgpu)->va),
"vgpu%d: opregion has been initialized already.\n",
vgpu->id))
return -EINVAL;
static int alloc_and_init_virt_opregion(struct intel_vgpu *vgpu)
{
u8 *buf;
struct opregion_header *header;
struct vbt v;
gvt_dbg_core("init vgpu%d opregion\n", vgpu->id);
vgpu_opregion(vgpu)->va = (void *)__get_free_pages(GFP_KERNEL |
__GFP_ZERO,
get_order(INTEL_GVT_OPREGION_SIZE));
if (!vgpu_opregion(vgpu)->va)
if (!vgpu_opregion(vgpu)->va) {
gvt_err("fail to get memory for vgpu virt opregion\n");
return -ENOMEM;
}
memcpy(vgpu_opregion(vgpu)->va, vgpu->gvt->opregion.opregion_va,
INTEL_GVT_OPREGION_SIZE);
for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++)
vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i;
/* emulated opregion with VBT mailbox only */
buf = (u8 *)vgpu_opregion(vgpu)->va;
header = (struct opregion_header *)buf;
memcpy(header->signature, OPREGION_SIGNATURE,
sizeof(OPREGION_SIGNATURE));
header->size = 0x8;
header->opregion_ver = 0x02000000;
header->mboxes = MBOX_VBT;
/* for unknown reason, the value in LID field is incorrect
* which block the windows guest, so workaround it by force
* setting it to "OPEN"
*/
buf = (u8 *)vgpu_opregion(vgpu)->va;
buf[INTEL_GVT_OPREGION_CLID] = 0x3;
/* emulated vbt from virt vbt generation */
virt_vbt_generation(&v);
memcpy(buf + INTEL_GVT_OPREGION_VBT_OFFSET, &v, sizeof(struct vbt));
return 0;
}
static int init_vgpu_opregion(struct intel_vgpu *vgpu, u32 gpa)
{
int i, ret;
if (WARN((vgpu_opregion(vgpu)->va),
"vgpu%d: opregion has been initialized already.\n",
vgpu->id))
return -EINVAL;
ret = alloc_and_init_virt_opregion(vgpu);
if (ret < 0)
return ret;
for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++)
vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i;
return 0;
}
......@@ -132,40 +343,6 @@ int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa)
return 0;
}
/**
* intel_gvt_clean_opregion - clean host opergion related stuffs
* @gvt: a GVT device
*
*/
void intel_gvt_clean_opregion(struct intel_gvt *gvt)
{
memunmap(gvt->opregion.opregion_va);
gvt->opregion.opregion_va = NULL;
}
/**
* intel_gvt_init_opregion - initialize host opergion related stuffs
* @gvt: a GVT device
*
* Returns:
* Zero on success, negative error code if failed.
*/
int intel_gvt_init_opregion(struct intel_gvt *gvt)
{
gvt_dbg_core("init host opregion\n");
pci_read_config_dword(gvt->dev_priv->drm.pdev, INTEL_GVT_PCI_OPREGION,
&gvt->opregion.opregion_pa);
gvt->opregion.opregion_va = memremap(gvt->opregion.opregion_pa,
INTEL_GVT_OPREGION_SIZE, MEMREMAP_WB);
if (!gvt->opregion.opregion_va) {
gvt_err("fail to map host opregion\n");
return -EFAULT;
}
return 0;
}
#define GVT_OPREGION_FUNC(scic) \
({ \
u32 __ret; \
......
......@@ -51,6 +51,9 @@
#define INTEL_GVT_OPREGION_PAGES 2
#define INTEL_GVT_OPREGION_SIZE (INTEL_GVT_OPREGION_PAGES * PAGE_SIZE)
#define INTEL_GVT_OPREGION_VBT_OFFSET 0x400
#define INTEL_GVT_OPREGION_VBT_SIZE \
(INTEL_GVT_OPREGION_SIZE - INTEL_GVT_OPREGION_VBT_OFFSET)
#define VGT_SPRSTRIDE(pipe) _PIPE(pipe, _SPRA_STRIDE, _PLANE_STRIDE_2_B)
......@@ -71,6 +74,7 @@
#define RB_HEAD_OFF_MASK ((1U << 21) - (1U << 2))
#define RB_TAIL_OFF_MASK ((1U << 21) - (1U << 3))
#define RB_TAIL_SIZE_MASK ((1U << 21) - (1U << 12))
#define _RING_CTL_BUF_SIZE(ctl) (((ctl) & RB_TAIL_SIZE_MASK) + GTT_PAGE_SIZE)
#define _RING_CTL_BUF_SIZE(ctl) (((ctl) & RB_TAIL_SIZE_MASK) + \
I915_GTT_PAGE_SIZE)
#endif
......@@ -147,6 +147,7 @@ static u32 gen9_render_mocs_L3[32];
static void handle_tlb_pending_event(struct intel_vgpu *vgpu, int ring_id)
{
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
struct intel_vgpu_submission *s = &vgpu->submission;
enum forcewake_domains fw;
i915_reg_t reg;
u32 regs[] = {
......@@ -160,7 +161,7 @@ static void handle_tlb_pending_event(struct intel_vgpu *vgpu, int ring_id)
if (WARN_ON(ring_id >= ARRAY_SIZE(regs)))
return;
if (!test_and_clear_bit(ring_id, (void *)vgpu->tlb_handle_pending))
if (!test_and_clear_bit(ring_id, (void *)s->tlb_handle_pending))
return;
reg = _MMIO(regs[ring_id]);
......@@ -208,7 +209,7 @@ static void load_mocs(struct intel_vgpu *vgpu, int ring_id)
offset.reg = regs[ring_id];
for (i = 0; i < 64; i++) {
gen9_render_mocs[ring_id][i] = I915_READ_FW(offset);
I915_WRITE(offset, vgpu_vreg(vgpu, offset));
I915_WRITE_FW(offset, vgpu_vreg(vgpu, offset));
offset.reg += 4;
}
......@@ -261,14 +262,15 @@ static void restore_mocs(struct intel_vgpu *vgpu, int ring_id)
static void switch_mmio_to_vgpu(struct intel_vgpu *vgpu, int ring_id)
{
struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
struct render_mmio *mmio;
u32 v;
int i, array_size;
u32 *reg_state = vgpu->shadow_ctx->engine[ring_id].lrc_reg_state;
struct intel_vgpu_submission *s = &vgpu->submission;
u32 *reg_state = s->shadow_ctx->engine[ring_id].lrc_reg_state;
u32 ctx_ctrl = reg_state[CTX_CONTEXT_CONTROL_VAL];
u32 inhibit_mask =
_MASKED_BIT_ENABLE(CTX_CTRL_ENGINE_CTX_RESTORE_INHIBIT);
i915_reg_t last_reg = _MMIO(0);
struct render_mmio *mmio;
u32 v;
int i, array_size;
if (IS_SKYLAKE(vgpu->gvt->dev_priv)
|| IS_KABYLAKE(vgpu->gvt->dev_priv)) {
......
This diff is collapsed.
......@@ -112,17 +112,18 @@ struct intel_vgpu_workload {
struct intel_shadow_wa_ctx wa_ctx;
};
/* Intel shadow batch buffer is a i915 gem object */
struct intel_shadow_bb_entry {
struct intel_vgpu_shadow_bb {
struct list_head list;
struct drm_i915_gem_object *obj;
struct i915_vma *vma;
void *va;
unsigned long len;
u32 *bb_start_cmd_va;
unsigned int clflush;
bool accessing;
};
#define workload_q_head(vgpu, ring_id) \
(&(vgpu->workload_q_head[ring_id]))
(&(vgpu->submission.workload_q_head[ring_id]))
#define queue_workload(workload) do { \
list_add_tail(&workload->list, \
......@@ -137,9 +138,23 @@ void intel_gvt_clean_workload_scheduler(struct intel_gvt *gvt);
void intel_gvt_wait_vgpu_idle(struct intel_vgpu *vgpu);
int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu);
int intel_vgpu_setup_submission(struct intel_vgpu *vgpu);
void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu);
void intel_vgpu_reset_submission(struct intel_vgpu *vgpu,
unsigned long engine_mask);
void intel_vgpu_clean_submission(struct intel_vgpu *vgpu);
int intel_vgpu_select_submission_ops(struct intel_vgpu *vgpu,
unsigned int interface);
extern const struct intel_vgpu_submission_ops
intel_vgpu_execlist_submission_ops;
struct intel_vgpu_workload *
intel_vgpu_create_workload(struct intel_vgpu *vgpu, int ring_id,
struct execlist_ctx_descriptor_format *desc);
void intel_vgpu_destroy_workload(struct intel_vgpu_workload *workload);
void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx);
#endif
......@@ -43,7 +43,10 @@ void populate_pvinfo_page(struct intel_vgpu *vgpu)
vgpu_vreg(vgpu, vgtif_reg(version_minor)) = 0;
vgpu_vreg(vgpu, vgtif_reg(display_ready)) = 0;
vgpu_vreg(vgpu, vgtif_reg(vgt_id)) = vgpu->id;
vgpu_vreg(vgpu, vgtif_reg(vgt_caps)) = VGT_CAPS_FULL_48BIT_PPGTT;
vgpu_vreg(vgpu, vgtif_reg(vgt_caps)) |= VGT_CAPS_HWSP_EMULATION;
vgpu_vreg(vgpu, vgtif_reg(avail_rs.mappable_gmadr.base)) =
vgpu_aperture_gmadr_base(vgpu);
vgpu_vreg(vgpu, vgtif_reg(avail_rs.mappable_gmadr.size)) =
......@@ -226,7 +229,7 @@ void intel_gvt_deactivate_vgpu(struct intel_vgpu *vgpu)
vgpu->active = false;
if (atomic_read(&vgpu->running_workload_num)) {
if (atomic_read(&vgpu->submission.running_workload_num)) {
mutex_unlock(&gvt->lock);
intel_gvt_wait_vgpu_idle(vgpu);
mutex_lock(&gvt->lock);
......@@ -252,10 +255,10 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu)
WARN(vgpu->active, "vGPU is still active!\n");
intel_gvt_debugfs_remove_vgpu(vgpu);
idr_remove(&gvt->vgpu_idr, vgpu->id);
intel_vgpu_clean_sched_policy(vgpu);
intel_vgpu_clean_gvt_context(vgpu);
intel_vgpu_clean_execlist(vgpu);
intel_vgpu_clean_submission(vgpu);
intel_vgpu_clean_display(vgpu);
intel_vgpu_clean_opregion(vgpu);
intel_vgpu_clean_gtt(vgpu);
......@@ -293,7 +296,7 @@ struct intel_vgpu *intel_gvt_create_idle_vgpu(struct intel_gvt *gvt)
vgpu->gvt = gvt;
for (i = 0; i < I915_NUM_ENGINES; i++)
INIT_LIST_HEAD(&vgpu->workload_q_head[i]);
INIT_LIST_HEAD(&vgpu->submission.workload_q_head[i]);
ret = intel_vgpu_init_sched_policy(vgpu);
if (ret)
......@@ -346,7 +349,6 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
vgpu->handle = param->handle;
vgpu->gvt = gvt;
vgpu->sched_ctl.weight = param->weight;
bitmap_zero(vgpu->tlb_handle_pending, I915_NUM_ENGINES);
intel_vgpu_init_cfg_space(vgpu, param->primary);
......@@ -372,26 +374,26 @@ static struct intel_vgpu *__intel_gvt_create_vgpu(struct intel_gvt *gvt,
if (ret)
goto out_clean_gtt;
ret = intel_vgpu_init_execlist(vgpu);
ret = intel_vgpu_setup_submission(vgpu);
if (ret)
goto out_clean_display;
ret = intel_vgpu_init_gvt_context(vgpu);
ret = intel_vgpu_init_sched_policy(vgpu);
if (ret)
goto out_clean_execlist;
goto out_clean_submission;
ret = intel_vgpu_init_sched_policy(vgpu);
ret = intel_gvt_debugfs_add_vgpu(vgpu);
if (ret)
goto out_clean_shadow_ctx;
goto out_clean_sched_policy;
mutex_unlock(&gvt->lock);
return vgpu;
out_clean_shadow_ctx:
intel_vgpu_clean_gvt_context(vgpu);
out_clean_execlist:
intel_vgpu_clean_execlist(vgpu);
out_clean_sched_policy:
intel_vgpu_clean_sched_policy(vgpu);
out_clean_submission:
intel_vgpu_clean_submission(vgpu);
out_clean_display:
intel_vgpu_clean_display(vgpu);
out_clean_gtt:
......@@ -500,10 +502,10 @@ void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
mutex_lock(&gvt->lock);
}
intel_vgpu_reset_execlist(vgpu, resetting_eng);
intel_vgpu_reset_submission(vgpu, resetting_eng);
/* full GPU reset or device model level reset */
if (engine_mask == ALL_ENGINES || dmlr) {
intel_vgpu_select_submission_ops(vgpu, 0);
/*fence will not be reset during virtual reset */
if (dmlr) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment