Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f1750e14 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-fixes-2017-01-19' of...

Merge tag 'drm-intel-fixes-2017-01-19' of git://anongit.freedesktop.org/git/drm-intel into drm-fixes

More GVT-g stuff than I'd like at this stage, but then again that's
pretty new and isolated so I'm not too worried.

* tag 'drm-intel-fixes-2017-01-19' of git://anongit.freedesktop.org/git/drm-intel: (26 commits)
  drm/i915: Ignore bogus plane coordinates on SKL when the plane is not visible
  drm/i915: Remove WaDisableLSQCROPERFforOCL KBL workaround.
  drm/i915/gvt: rewrite gt reset handler using new function intel_gvt_reset_vgpu_locked
  drm/i915/gvt: fix vGPU instance reuse issues by vGPU reset function
  drm/i915/gvt: introduce intel_vgpu_reset_mmio() to reset mmio space
  drm/i915/gvt: move mmio init/clean function to mmio.c
  drm/i915/gvt: introduce intel_vgpu_reset_cfg_space to reset configuration space
  drm/i915/gvt: move cfg space inititation function to cfg_space.c
  drm/i915/gvt: introuduce intel_vgpu_reset_gtt() to reset gtt
  drm/i915/gvt: introudce intel_vgpu_reset_resource() to reset vgpu resource state
  drm/i915: Fix phys pwrite for struct_mutex-less operation
  drm/i915: Clear ret before unbinding in i915_gem_evict_something()
  drm/i915/gvt: cleanup GFP flags
  drm/i915/gvt/kvmgt: return meaningful error for vgpu creating failure
  drm/i915/gvt: cleanup opregion memory allocation code
  drm/i915/gvt: destroy the allocated idr on vgpu creating failures
  drm/i915/gvt: init/destroy vgpu_idr properly
  drm/i915/gvt: dec vgpu->running_workload_num after the workload is really done
  drm/i915/gvt: fix use after free for workload
  drm/i915/gvt: remove duplicated definition
  ...
parents 9afe69d5 3bfdfdcb
Loading
Loading
Loading
Loading
+27 −9
Original line number Diff line number Diff line
@@ -37,13 +37,6 @@
#include "i915_drv.h"
#include "gvt.h"

#define MB_TO_BYTES(mb) ((mb) << 20ULL)
#define BYTES_TO_MB(b) ((b) >> 20ULL)

#define HOST_LOW_GM_SIZE MB_TO_BYTES(128)
#define HOST_HIGH_GM_SIZE MB_TO_BYTES(384)
#define HOST_FENCE 4

static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm)
{
	struct intel_gvt *gvt = vgpu->gvt;
@@ -165,6 +158,14 @@ void intel_vgpu_write_fence(struct intel_vgpu *vgpu,
	POSTING_READ(fence_reg_lo);
}

static void _clear_vgpu_fence(struct intel_vgpu *vgpu)
{
	int i;

	for (i = 0; i < vgpu_fence_sz(vgpu); i++)
		intel_vgpu_write_fence(vgpu, i, 0);
}

static void free_vgpu_fence(struct intel_vgpu *vgpu)
{
	struct intel_gvt *gvt = vgpu->gvt;
@@ -178,9 +179,9 @@ static void free_vgpu_fence(struct intel_vgpu *vgpu)
	intel_runtime_pm_get(dev_priv);

	mutex_lock(&dev_priv->drm.struct_mutex);
	_clear_vgpu_fence(vgpu);
	for (i = 0; i < vgpu_fence_sz(vgpu); i++) {
		reg = vgpu->fence.regs[i];
		intel_vgpu_write_fence(vgpu, i, 0);
		list_add_tail(&reg->link,
			      &dev_priv->mm.fence_list);
	}
@@ -208,13 +209,14 @@ static int alloc_vgpu_fence(struct intel_vgpu *vgpu)
			continue;
		list_del(pos);
		vgpu->fence.regs[i] = reg;
		intel_vgpu_write_fence(vgpu, i, 0);
		if (++i == vgpu_fence_sz(vgpu))
			break;
	}
	if (i != vgpu_fence_sz(vgpu))
		goto out_free_fence;

	_clear_vgpu_fence(vgpu);

	mutex_unlock(&dev_priv->drm.struct_mutex);
	intel_runtime_pm_put(dev_priv);
	return 0;
@@ -313,6 +315,22 @@ void intel_vgpu_free_resource(struct intel_vgpu *vgpu)
	free_resource(vgpu);
}

/**
 * intel_vgpu_reset_resource - reset resource state owned by a vGPU
 * @vgpu: a vGPU
 *
 * This function is used to reset resource state owned by a vGPU.
 *
 */
void intel_vgpu_reset_resource(struct intel_vgpu *vgpu)
{
	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;

	intel_runtime_pm_get(dev_priv);
	_clear_vgpu_fence(vgpu);
	intel_runtime_pm_put(dev_priv);
}

/**
 * intel_alloc_vgpu_resource - allocate HW resource for a vGPU
 * @vgpu: vGPU
+74 −0
Original line number Diff line number Diff line
@@ -282,3 +282,77 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset,
	}
	return 0;
}

/**
 * intel_vgpu_init_cfg_space - init vGPU configuration space when create vGPU
 *
 * @vgpu: a vGPU
 * @primary: is the vGPU presented as primary
 *
 */
void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu,
			       bool primary)
{
	struct intel_gvt *gvt = vgpu->gvt;
	const struct intel_gvt_device_info *info = &gvt->device_info;
	u16 *gmch_ctl;
	int i;

	memcpy(vgpu_cfg_space(vgpu), gvt->firmware.cfg_space,
	       info->cfg_space_size);

	if (!primary) {
		vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] =
			INTEL_GVT_PCI_CLASS_VGA_OTHER;
		vgpu_cfg_space(vgpu)[PCI_CLASS_PROG] =
			INTEL_GVT_PCI_CLASS_VGA_OTHER;
	}

	/* Show guest that there isn't any stolen memory.*/
	gmch_ctl = (u16 *)(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_GMCH_CONTROL);
	*gmch_ctl &= ~(BDW_GMCH_GMS_MASK << BDW_GMCH_GMS_SHIFT);

	intel_vgpu_write_pci_bar(vgpu, PCI_BASE_ADDRESS_2,
				 gvt_aperture_pa_base(gvt), true);

	vgpu_cfg_space(vgpu)[PCI_COMMAND] &= ~(PCI_COMMAND_IO
					     | PCI_COMMAND_MEMORY
					     | PCI_COMMAND_MASTER);
	/*
	 * Clear the bar upper 32bit and let guest to assign the new value
	 */
	memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_1, 0, 4);
	memset(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_3, 0, 4);
	memset(vgpu_cfg_space(vgpu) + INTEL_GVT_PCI_OPREGION, 0, 4);

	for (i = 0; i < INTEL_GVT_MAX_BAR_NUM; i++) {
		vgpu->cfg_space.bar[i].size = pci_resource_len(
					      gvt->dev_priv->drm.pdev, i * 2);
		vgpu->cfg_space.bar[i].tracked = false;
	}
}

/**
 * intel_vgpu_reset_cfg_space - reset vGPU configuration space
 *
 * @vgpu: a vGPU
 *
 */
void intel_vgpu_reset_cfg_space(struct intel_vgpu *vgpu)
{
	u8 cmd = vgpu_cfg_space(vgpu)[PCI_COMMAND];
	bool primary = vgpu_cfg_space(vgpu)[PCI_CLASS_DEVICE] !=
				INTEL_GVT_PCI_CLASS_VGA_OTHER;

	if (cmd & PCI_COMMAND_MEMORY) {
		trap_gttmmio(vgpu, false);
		map_aperture(vgpu, false);
	}

	/**
	 * Currently we only do such reset when vGPU is not
	 * owned by any VM, so we simply restore entire cfg
	 * space to default value.
	 */
	intel_vgpu_init_cfg_space(vgpu, primary);
}
+44 −37
Original line number Diff line number Diff line
@@ -240,15 +240,8 @@ static inline int get_pse_type(int type)
static u64 read_pte64(struct drm_i915_private *dev_priv, unsigned long index)
{
	void __iomem *addr = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + index;
	u64 pte;

#ifdef readq
	pte = readq(addr);
#else
	pte = ioread32(addr);
	pte |= (u64)ioread32(addr + 4) << 32;
#endif
	return pte;
	return readq(addr);
}

static void write_pte64(struct drm_i915_private *dev_priv,
@@ -256,12 +249,8 @@ static void write_pte64(struct drm_i915_private *dev_priv,
{
	void __iomem *addr = (gen8_pte_t __iomem *)dev_priv->ggtt.gsm + index;

#ifdef writeq
	writeq(pte, addr);
#else
	iowrite32((u32)pte, addr);
	iowrite32(pte >> 32, addr + 4);
#endif

	I915_WRITE(GFX_FLSH_CNTL_GEN6, GFX_FLSH_CNTL_EN);
	POSTING_READ(GFX_FLSH_CNTL_GEN6);
}
@@ -1380,8 +1369,7 @@ static int gen8_mm_alloc_page_table(struct intel_vgpu_mm *mm)
			info->gtt_entry_size;
		mem = kzalloc(mm->has_shadow_page_table ?
			mm->page_table_entry_size * 2
				: mm->page_table_entry_size,
			GFP_ATOMIC);
				: mm->page_table_entry_size, GFP_KERNEL);
		if (!mem)
			return -ENOMEM;
		mm->virtual_page_table = mem;
@@ -1532,7 +1520,7 @@ struct intel_vgpu_mm *intel_vgpu_create_mm(struct intel_vgpu *vgpu,
	struct intel_vgpu_mm *mm;
	int ret;

	mm = kzalloc(sizeof(*mm), GFP_ATOMIC);
	mm = kzalloc(sizeof(*mm), GFP_KERNEL);
	if (!mm) {
		ret = -ENOMEM;
		goto fail;
@@ -1886,30 +1874,27 @@ static int alloc_scratch_pages(struct intel_vgpu *vgpu,
	struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
	int page_entry_num = GTT_PAGE_SIZE >>
				vgpu->gvt->device_info.gtt_entry_size_shift;
	struct page *scratch_pt;
	void *scratch_pt;
	unsigned long mfn;
	int i;
	void *p;

	if (WARN_ON(type < GTT_TYPE_PPGTT_PTE_PT || type >= GTT_TYPE_MAX))
		return -EINVAL;

	scratch_pt = alloc_page(GFP_KERNEL | GFP_ATOMIC | __GFP_ZERO);
	scratch_pt = (void *)get_zeroed_page(GFP_KERNEL);
	if (!scratch_pt) {
		gvt_err("fail to allocate scratch page\n");
		return -ENOMEM;
	}

	p = kmap_atomic(scratch_pt);
	mfn = intel_gvt_hypervisor_virt_to_mfn(p);
	mfn = intel_gvt_hypervisor_virt_to_mfn(scratch_pt);
	if (mfn == INTEL_GVT_INVALID_ADDR) {
		gvt_err("fail to translate vaddr:0x%llx\n", (u64)p);
		kunmap_atomic(p);
		__free_page(scratch_pt);
		gvt_err("fail to translate vaddr:0x%lx\n", (unsigned long)scratch_pt);
		free_page((unsigned long)scratch_pt);
		return -EFAULT;
	}
	gtt->scratch_pt[type].page_mfn = mfn;
	gtt->scratch_pt[type].page = scratch_pt;
	gtt->scratch_pt[type].page = virt_to_page(scratch_pt);
	gvt_dbg_mm("vgpu%d create scratch_pt: type %d mfn=0x%lx\n",
			vgpu->id, type, mfn);

@@ -1918,7 +1903,7 @@ static int alloc_scratch_pages(struct intel_vgpu *vgpu,
	 * scratch_pt[type] indicate the scratch pt/scratch page used by the
	 * 'type' pt.
	 * e.g. scratch_pt[GTT_TYPE_PPGTT_PDE_PT] is used by
	 * GTT_TYPE_PPGTT_PDE_PT level pt, that means this scatch_pt it self
	 * GTT_TYPE_PPGTT_PDE_PT level pt, that means this scratch_pt it self
	 * is GTT_TYPE_PPGTT_PTE_PT, and full filled by scratch page mfn.
	 */
	if (type > GTT_TYPE_PPGTT_PTE_PT && type < GTT_TYPE_MAX) {
@@ -1936,11 +1921,9 @@ static int alloc_scratch_pages(struct intel_vgpu *vgpu,
			se.val64 |= PPAT_CACHED_INDEX;

		for (i = 0; i < page_entry_num; i++)
			ops->set_entry(p, &se, i, false, 0, vgpu);
			ops->set_entry(scratch_pt, &se, i, false, 0, vgpu);
	}

	kunmap_atomic(p);

	return 0;
}

@@ -2208,7 +2191,7 @@ int intel_vgpu_g2v_destroy_ppgtt_mm(struct intel_vgpu *vgpu,
int intel_gvt_init_gtt(struct intel_gvt *gvt)
{
	int ret;
	void *page_addr;
	void *page;

	gvt_dbg_core("init gtt\n");

@@ -2221,17 +2204,14 @@ int intel_gvt_init_gtt(struct intel_gvt *gvt)
		return -ENODEV;
	}

	gvt->gtt.scratch_ggtt_page =
		alloc_page(GFP_KERNEL | GFP_ATOMIC | __GFP_ZERO);
	if (!gvt->gtt.scratch_ggtt_page) {
	page = (void *)get_zeroed_page(GFP_KERNEL);
	if (!page) {
		gvt_err("fail to allocate scratch ggtt page\n");
		return -ENOMEM;
	}
	gvt->gtt.scratch_ggtt_page = virt_to_page(page);

	page_addr = page_address(gvt->gtt.scratch_ggtt_page);

	gvt->gtt.scratch_ggtt_mfn =
		intel_gvt_hypervisor_virt_to_mfn(page_addr);
	gvt->gtt.scratch_ggtt_mfn = intel_gvt_hypervisor_virt_to_mfn(page);
	if (gvt->gtt.scratch_ggtt_mfn == INTEL_GVT_INVALID_ADDR) {
		gvt_err("fail to translate scratch ggtt page\n");
		__free_page(gvt->gtt.scratch_ggtt_page);
@@ -2297,3 +2277,30 @@ void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu)
	for (offset = 0; offset < num_entries; offset++)
		ops->set_entry(NULL, &e, index + offset, false, 0, vgpu);
}

/**
 * intel_vgpu_reset_gtt - reset the all GTT related status
 * @vgpu: a vGPU
 * @dmlr: true for vGPU Device Model Level Reset, false for GT Reset
 *
 * This function is called from vfio core to reset reset all
 * GTT related status, including GGTT, PPGTT, scratch page.
 *
 */
void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu, bool dmlr)
{
	int i;

	ppgtt_free_all_shadow_page(vgpu);
	if (!dmlr)
		return;

	intel_vgpu_reset_ggtt(vgpu);

	/* clear scratch page for security */
	for (i = GTT_TYPE_PPGTT_PTE_PT; i < GTT_TYPE_MAX; i++) {
		if (vgpu->gtt.scratch_pt[i].page != NULL)
			memset(page_address(vgpu->gtt.scratch_pt[i].page),
				0, PAGE_SIZE);
	}
}
+1 −0
Original line number Diff line number Diff line
@@ -208,6 +208,7 @@ extern void intel_vgpu_clean_gtt(struct intel_vgpu *vgpu);
void intel_vgpu_reset_ggtt(struct intel_vgpu *vgpu);

extern int intel_gvt_init_gtt(struct intel_gvt *gvt);
extern void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu, bool dmlr);
extern void intel_gvt_clean_gtt(struct intel_gvt *gvt);

extern struct intel_vgpu_mm *intel_gvt_find_ppgtt_mm(struct intel_vgpu *vgpu,
+7 −1
Original line number Diff line number Diff line
@@ -201,6 +201,8 @@ void intel_gvt_clean_device(struct drm_i915_private *dev_priv)
	intel_gvt_hypervisor_host_exit(&dev_priv->drm.pdev->dev, gvt);
	intel_gvt_clean_vgpu_types(gvt);

	idr_destroy(&gvt->vgpu_idr);

	kfree(dev_priv->gvt);
	dev_priv->gvt = NULL;
}
@@ -237,6 +239,8 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)

	gvt_dbg_core("init gvt device\n");

	idr_init(&gvt->vgpu_idr);

	mutex_init(&gvt->lock);
	gvt->dev_priv = dev_priv;

@@ -244,7 +248,7 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)

	ret = intel_gvt_setup_mmio_info(gvt);
	if (ret)
		return ret;
		goto out_clean_idr;

	ret = intel_gvt_load_firmware(gvt);
	if (ret)
@@ -313,6 +317,8 @@ int intel_gvt_init_device(struct drm_i915_private *dev_priv)
	intel_gvt_free_firmware(gvt);
out_clean_mmio_info:
	intel_gvt_clean_mmio_info(gvt);
out_clean_idr:
	idr_destroy(&gvt->vgpu_idr);
	kfree(gvt);
	return ret;
}
Loading