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

Commit f80c2fb6 authored by Jani Nikula's avatar Jani Nikula
Browse files

Merge tag 'gvt-fixes-2017-01-16' of https://github.com/01org/gvt-linux into drm-intel-fixes



gvt-fixes-2017-01-16

vGPU reset fixes from Changbin.

Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
parents e4621b73 c34eaa8d
Loading
Loading
Loading
Loading
+27 −2
Original line number Diff line number Diff line
@@ -158,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;
@@ -171,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);
	}
@@ -201,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;
@@ -306,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);
}
+27 −0
Original line number Diff line number Diff line
@@ -2277,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
@@ -323,6 +323,7 @@ struct intel_vgpu_creation_params {

int intel_vgpu_alloc_resource(struct intel_vgpu *vgpu,
			      struct intel_vgpu_creation_params *param);
void intel_vgpu_reset_resource(struct intel_vgpu *vgpu);
void intel_vgpu_free_resource(struct intel_vgpu *vgpu);
void intel_vgpu_write_fence(struct intel_vgpu *vgpu,
	u32 fence, u64 value);
@@ -375,6 +376,8 @@ void intel_gvt_clean_vgpu_types(struct intel_gvt *gvt);
struct intel_vgpu *intel_gvt_create_vgpu(struct intel_gvt *gvt,
					 struct intel_vgpu_type *type);
void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu);
void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr,
				 unsigned int engine_mask);
void intel_gvt_reset_vgpu(struct intel_vgpu *vgpu);


@@ -411,6 +414,10 @@ int intel_gvt_ggtt_index_g2h(struct intel_vgpu *vgpu, unsigned long g_index,
int intel_gvt_ggtt_h2g_index(struct intel_vgpu *vgpu, unsigned long h_index,
			     unsigned long *g_index);

void intel_vgpu_init_cfg_space(struct intel_vgpu *vgpu,
		bool primary);
void intel_vgpu_reset_cfg_space(struct intel_vgpu *vgpu);

int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset,
		void *p_data, unsigned int bytes);

@@ -424,7 +431,6 @@ void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu);
int intel_vgpu_init_opregion(struct intel_vgpu *vgpu, u32 gpa);

int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci);
int setup_vgpu_mmio(struct intel_vgpu *vgpu);
void populate_pvinfo_page(struct intel_vgpu *vgpu);

struct intel_gvt_ops {
Loading