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

Commit baa68f6e authored by Daniel Vetter's avatar Daniel Vetter
Browse files

Merge tag 'gvt-next-2017-08-15' of https://github.com/01org/gvt-linux into drm-intel-next-queued



gvt-next-2017-08-15

gvt update for 4.14
- MMIO save/restore optimization (Changbin)
- Split workload scan vs. dispatch for more parallel exec (Ping)
- vGPU full 48bit ppgtt support (Joonas, Tina)
- vGPU hw id expose for perf (Zhenyu)
- other misc cleanup and fixes

Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Link: https://patchwork.freedesktop.org/patch/msgid/20170815023940.skhjfcsyrao7axqi@zhen-hp.sh.intel.com
parents d59814a5 6b3816d6
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -285,8 +285,8 @@ static int alloc_resource(struct intel_vgpu *vgpu,
	return 0;

no_enough_resource:
	gvt_vgpu_err("fail to allocate resource %s\n", item);
	gvt_vgpu_err("request %luMB avail %luMB max %luMB taken %luMB\n",
	gvt_err("fail to allocate resource %s\n", item);
	gvt_err("request %luMB avail %luMB max %luMB taken %luMB\n",
		BYTES_TO_MB(request), BYTES_TO_MB(avail),
		BYTES_TO_MB(max), BYTES_TO_MB(taken));
	return -ENOSPC;
+4 −4
Original line number Diff line number Diff line
@@ -1382,13 +1382,13 @@ static inline int cmd_address_audit(struct parser_exec_state *s,
			ret = -EINVAL;
			goto err;
		}
	} else if ((!vgpu_gmadr_is_valid(s->vgpu, guest_gma)) ||
			(!vgpu_gmadr_is_valid(s->vgpu,
					      guest_gma + op_size - 1))) {
	} else if (!intel_gvt_ggtt_validate_range(vgpu, guest_gma, op_size)) {
		ret = -EINVAL;
		goto err;
	}

	return 0;

err:
	gvt_vgpu_err("cmd_parser: Malicious %s detected, addr=0x%lx, len=%d!\n",
			s->info->name, guest_gma, op_size);
@@ -2647,7 +2647,7 @@ static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload)
	return 0;
}

int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)
int intel_gvt_scan_and_shadow_ringbuffer(struct intel_vgpu_workload *workload)
{
	int ret;
	struct intel_vgpu *vgpu = workload->vgpu;
+1 −1
Original line number Diff line number Diff line
@@ -42,7 +42,7 @@ void intel_gvt_clean_cmd_parser(struct intel_gvt *gvt);

int intel_gvt_init_cmd_parser(struct intel_gvt *gvt);

int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload);
int intel_gvt_scan_and_shadow_ringbuffer(struct intel_vgpu_workload *workload);

int intel_gvt_scan_and_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx);

+15 −0
Original line number Diff line number Diff line
@@ -605,6 +605,7 @@ static int submit_context(struct intel_vgpu *vgpu, int ring_id,
	struct list_head *q = workload_q_head(vgpu, ring_id);
	struct intel_vgpu_workload *last_workload = get_last_workload(q);
	struct intel_vgpu_workload *workload = NULL;
	struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
	u64 ring_context_gpa;
	u32 head, tail, start, ctl, ctx_ctl, per_ctx, indirect_ctx;
	int ret;
@@ -668,6 +669,7 @@ static int submit_context(struct intel_vgpu *vgpu, int ring_id,
	workload->complete = complete_execlist_workload;
	workload->status = -EINPROGRESS;
	workload->emulate_schedule_in = emulate_schedule_in;
	workload->shadowed = false;

	if (ring_id == RCS) {
		intel_gvt_hypervisor_read_gpa(vgpu, ring_context_gpa +
@@ -701,6 +703,17 @@ static int submit_context(struct intel_vgpu *vgpu, int ring_id,
		return ret;
	}

	/* Only scan and shadow the first workload in the queue
	 * as there is only one pre-allocated buf-obj for shadow.
	 */
	if (list_empty(workload_q_head(vgpu, ring_id))) {
		intel_runtime_pm_get(dev_priv);
		mutex_lock(&dev_priv->drm.struct_mutex);
		intel_gvt_scan_and_shadow_workload(workload);
		mutex_unlock(&dev_priv->drm.struct_mutex);
		intel_runtime_pm_put(dev_priv);
	}

	queue_workload(workload);
	return 0;
}
@@ -783,6 +796,8 @@ static void clean_workloads(struct intel_vgpu *vgpu, unsigned long engine_mask)
			list_del_init(&pos->list);
			free_workload(pos);
		}

		clear_bit(engine->id, vgpu->shadow_ctx_desc_updated);
	}
}

+79 −49
Original line number Diff line number Diff line
@@ -259,7 +259,7 @@ static void write_pte64(struct drm_i915_private *dev_priv,
	writeq(pte, addr);
}

static inline struct intel_gvt_gtt_entry *gtt_get_entry64(void *pt,
static inline int gtt_get_entry64(void *pt,
		struct intel_gvt_gtt_entry *e,
		unsigned long index, bool hypervisor_access, unsigned long gpa,
		struct intel_vgpu *vgpu)
@@ -268,22 +268,23 @@ static inline struct intel_gvt_gtt_entry *gtt_get_entry64(void *pt,
	int ret;

	if (WARN_ON(info->gtt_entry_size != 8))
		return e;
		return -EINVAL;

	if (hypervisor_access) {
		ret = intel_gvt_hypervisor_read_gpa(vgpu, gpa +
				(index << info->gtt_entry_size_shift),
				&e->val64, 8);
		WARN_ON(ret);
		if (WARN_ON(ret))
			return ret;
	} else if (!pt) {
		e->val64 = read_pte64(vgpu->gvt->dev_priv, index);
	} else {
		e->val64 = *((u64 *)pt + index);
	}
	return e;
	return 0;
}

static inline struct intel_gvt_gtt_entry *gtt_set_entry64(void *pt,
static inline int gtt_set_entry64(void *pt,
		struct intel_gvt_gtt_entry *e,
		unsigned long index, bool hypervisor_access, unsigned long gpa,
		struct intel_vgpu *vgpu)
@@ -292,19 +293,20 @@ static inline struct intel_gvt_gtt_entry *gtt_set_entry64(void *pt,
	int ret;

	if (WARN_ON(info->gtt_entry_size != 8))
		return e;
		return -EINVAL;

	if (hypervisor_access) {
		ret = intel_gvt_hypervisor_write_gpa(vgpu, gpa +
				(index << info->gtt_entry_size_shift),
				&e->val64, 8);
		WARN_ON(ret);
		if (WARN_ON(ret))
			return ret;
	} else if (!pt) {
		write_pte64(vgpu->gvt->dev_priv, index, e->val64);
	} else {
		*((u64 *)pt + index) = e->val64;
	}
	return e;
	return 0;
}

#define GTT_HAW 46
@@ -445,21 +447,25 @@ static int gtt_entry_p2m(struct intel_vgpu *vgpu, struct intel_gvt_gtt_entry *p,
/*
 * MM helpers.
 */
struct intel_gvt_gtt_entry *intel_vgpu_mm_get_entry(struct intel_vgpu_mm *mm,
int intel_vgpu_mm_get_entry(struct intel_vgpu_mm *mm,
		void *page_table, struct intel_gvt_gtt_entry *e,
		unsigned long index)
{
	struct intel_gvt *gvt = mm->vgpu->gvt;
	struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
	int ret;

	e->type = mm->page_table_entry_type;

	ops->get_entry(page_table, e, index, false, 0, mm->vgpu);
	ret = ops->get_entry(page_table, e, index, false, 0, mm->vgpu);
	if (ret)
		return ret;

	ops->test_pse(e);
	return e;
	return 0;
}

struct intel_gvt_gtt_entry *intel_vgpu_mm_set_entry(struct intel_vgpu_mm *mm,
int intel_vgpu_mm_set_entry(struct intel_vgpu_mm *mm,
		void *page_table, struct intel_gvt_gtt_entry *e,
		unsigned long index)
{
@@ -472,7 +478,7 @@ struct intel_gvt_gtt_entry *intel_vgpu_mm_set_entry(struct intel_vgpu_mm *mm,
/*
 * PPGTT shadow page table helpers.
 */
static inline struct intel_gvt_gtt_entry *ppgtt_spt_get_entry(
static inline int ppgtt_spt_get_entry(
		struct intel_vgpu_ppgtt_spt *spt,
		void *page_table, int type,
		struct intel_gvt_gtt_entry *e, unsigned long index,
@@ -480,20 +486,24 @@ static inline struct intel_gvt_gtt_entry *ppgtt_spt_get_entry(
{
	struct intel_gvt *gvt = spt->vgpu->gvt;
	struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;
	int ret;

	e->type = get_entry_type(type);

	if (WARN(!gtt_type_is_entry(e->type), "invalid entry type\n"))
		return e;
		return -EINVAL;

	ops->get_entry(page_table, e, index, guest,
	ret = ops->get_entry(page_table, e, index, guest,
			spt->guest_page.gfn << GTT_PAGE_SHIFT,
			spt->vgpu);
	if (ret)
		return ret;

	ops->test_pse(e);
	return e;
	return 0;
}

static inline struct intel_gvt_gtt_entry *ppgtt_spt_set_entry(
static inline int ppgtt_spt_set_entry(
		struct intel_vgpu_ppgtt_spt *spt,
		void *page_table, int type,
		struct intel_gvt_gtt_entry *e, unsigned long index,
@@ -503,7 +513,7 @@ static inline struct intel_gvt_gtt_entry *ppgtt_spt_set_entry(
	struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops;

	if (WARN(!gtt_type_is_entry(e->type), "invalid entry type\n"))
		return e;
		return -EINVAL;

	return ops->set_entry(page_table, e, index, guest,
			spt->guest_page.gfn << GTT_PAGE_SHIFT,
@@ -792,13 +802,13 @@ static struct intel_vgpu_ppgtt_spt *ppgtt_find_shadow_page(

#define for_each_present_guest_entry(spt, e, i) \
	for (i = 0; i < pt_entries(spt); i++) \
	if (spt->vgpu->gvt->gtt.pte_ops->test_present( \
		ppgtt_get_guest_entry(spt, e, i)))
		if (!ppgtt_get_guest_entry(spt, e, i) && \
		    spt->vgpu->gvt->gtt.pte_ops->test_present(e))

#define for_each_present_shadow_entry(spt, e, i) \
	for (i = 0; i < pt_entries(spt); i++) \
	if (spt->vgpu->gvt->gtt.pte_ops->test_present( \
		ppgtt_get_shadow_entry(spt, e, i)))
		if (!ppgtt_get_shadow_entry(spt, e, i) && \
		    spt->vgpu->gvt->gtt.pte_ops->test_present(e))

static void ppgtt_get_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
{
@@ -979,29 +989,26 @@ static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt)
}

static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_guest_page *gpt,
		unsigned long index)
		struct intel_gvt_gtt_entry *se, unsigned long index)
{
	struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt);
	struct intel_vgpu_shadow_page *sp = &spt->shadow_page;
	struct intel_vgpu *vgpu = spt->vgpu;
	struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
	struct intel_gvt_gtt_entry e;
	int ret;

	ppgtt_get_shadow_entry(spt, &e, index);

	trace_gpt_change(spt->vgpu->id, "remove", spt, sp->type, e.val64,
	trace_gpt_change(spt->vgpu->id, "remove", spt, sp->type, se->val64,
			 index);

	if (!ops->test_present(&e))
	if (!ops->test_present(se))
		return 0;

	if (ops->get_pfn(&e) == vgpu->gtt.scratch_pt[sp->type].page_mfn)
	if (ops->get_pfn(se) == vgpu->gtt.scratch_pt[sp->type].page_mfn)
		return 0;

	if (gtt_type_is_pt(get_next_pt_type(e.type))) {
	if (gtt_type_is_pt(get_next_pt_type(se->type))) {
		struct intel_vgpu_ppgtt_spt *s =
			ppgtt_find_shadow_page(vgpu, ops->get_pfn(&e));
			ppgtt_find_shadow_page(vgpu, ops->get_pfn(se));
		if (!s) {
			gvt_vgpu_err("fail to find guest page\n");
			ret = -ENXIO;
@@ -1011,12 +1018,10 @@ static int ppgtt_handle_guest_entry_removal(struct intel_vgpu_guest_page *gpt,
		if (ret)
			goto fail;
	}
	ops->set_pfn(&e, vgpu->gtt.scratch_pt[sp->type].page_mfn);
	ppgtt_set_shadow_entry(spt, &e, index);
	return 0;
fail:
	gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d\n",
			spt, e.val64, e.type);
			spt, se->val64, se->type);
	return ret;
}

@@ -1236,22 +1241,37 @@ static int ppgtt_handle_guest_write_page_table(
{
	struct intel_vgpu_ppgtt_spt *spt = guest_page_to_ppgtt_spt(gpt);
	struct intel_vgpu *vgpu = spt->vgpu;
	int type = spt->shadow_page.type;
	struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
	struct intel_gvt_gtt_entry se;

	int ret;
	int new_present;

	new_present = ops->test_present(we);

	ret = ppgtt_handle_guest_entry_removal(gpt, index);
	if (ret)
		goto fail;
	/*
	 * Adding the new entry first and then removing the old one, that can
	 * guarantee the ppgtt table is validated during the window between
	 * adding and removal.
	 */
	ppgtt_get_shadow_entry(spt, &se, index);

	if (new_present) {
		ret = ppgtt_handle_guest_entry_add(gpt, we, index);
		if (ret)
			goto fail;
	}

	ret = ppgtt_handle_guest_entry_removal(gpt, &se, index);
	if (ret)
		goto fail;

	if (!new_present) {
		ops->set_pfn(&se, vgpu->gtt.scratch_pt[type].page_mfn);
		ppgtt_set_shadow_entry(spt, &se, index);
	}

	return 0;
fail:
	gvt_vgpu_err("fail: shadow page %p guest entry 0x%llx type %d.\n",
@@ -1323,7 +1343,7 @@ static int ppgtt_handle_guest_write_page_table_bytes(void *gp,
	struct intel_vgpu *vgpu = spt->vgpu;
	struct intel_gvt_gtt_pte_ops *ops = vgpu->gvt->gtt.pte_ops;
	const struct intel_gvt_device_info *info = &vgpu->gvt->device_info;
	struct intel_gvt_gtt_entry we;
	struct intel_gvt_gtt_entry we, se;
	unsigned long index;
	int ret;

@@ -1339,7 +1359,8 @@ static int ppgtt_handle_guest_write_page_table_bytes(void *gp,
			return ret;
	} else {
		if (!test_bit(index, spt->post_shadow_bitmap)) {
			ret = ppgtt_handle_guest_entry_removal(gpt, index);
			ppgtt_get_shadow_entry(spt, &se, index);
			ret = ppgtt_handle_guest_entry_removal(gpt, &se, index);
			if (ret)
				return ret;
		}
@@ -1713,8 +1734,10 @@ unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma)
		if (!vgpu_gmadr_is_valid(vgpu, gma))
			goto err;

		ggtt_get_guest_entry(mm, &e,
		ret = ggtt_get_guest_entry(mm, &e,
				gma_ops->gma_to_ggtt_pte_index(gma));
		if (ret)
			goto err;
		gpa = (pte_ops->get_pfn(&e) << GTT_PAGE_SHIFT)
			+ (gma & ~GTT_PAGE_MASK);

@@ -1724,7 +1747,9 @@ unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma)

	switch (mm->page_table_level) {
	case 4:
		ppgtt_get_shadow_root_entry(mm, &e, 0);
		ret = ppgtt_get_shadow_root_entry(mm, &e, 0);
		if (ret)
			goto err;
		gma_index[0] = gma_ops->gma_to_pml4_index(gma);
		gma_index[1] = gma_ops->gma_to_l4_pdp_index(gma);
		gma_index[2] = gma_ops->gma_to_pde_index(gma);
@@ -1732,15 +1757,19 @@ unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma)
		index = 4;
		break;
	case 3:
		ppgtt_get_shadow_root_entry(mm, &e,
		ret = ppgtt_get_shadow_root_entry(mm, &e,
				gma_ops->gma_to_l3_pdp_index(gma));
		if (ret)
			goto err;
		gma_index[0] = gma_ops->gma_to_pde_index(gma);
		gma_index[1] = gma_ops->gma_to_pte_index(gma);
		index = 2;
		break;
	case 2:
		ppgtt_get_shadow_root_entry(mm, &e,
		ret = ppgtt_get_shadow_root_entry(mm, &e,
				gma_ops->gma_to_pde_index(gma));
		if (ret)
			goto err;
		gma_index[0] = gma_ops->gma_to_pte_index(gma);
		index = 1;
		break;
@@ -1755,6 +1784,11 @@ unsigned long intel_vgpu_gma_to_gpa(struct intel_vgpu_mm *mm, unsigned long gma)
			(i == index - 1));
		if (ret)
			goto err;

		if (!pte_ops->test_present(&e)) {
			gvt_dbg_core("GMA 0x%lx is not present\n", gma);
			goto err;
		}
	}

	gpa = (pte_ops->get_pfn(&e) << GTT_PAGE_SHIFT)
@@ -2329,13 +2363,12 @@ void intel_vgpu_reset_ggtt(struct intel_vgpu *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)
void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu)
{
	int i;

@@ -2347,9 +2380,6 @@ void intel_vgpu_reset_gtt(struct intel_vgpu *vgpu, bool dmlr)
	 */
	intel_vgpu_free_mm(vgpu, INTEL_GVT_MM_PPGTT);

	if (!dmlr)
		return;

	intel_vgpu_reset_ggtt(vgpu);

	/* clear scratch page for security */
Loading