Unverified Commit a9a84aac authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!11378 drm/i915/gem: Fix Virtual Memory mapping boundaries calculation

parents cba54d55 0cbf14f0
Loading
Loading
Loading
Loading
+42 −5
Original line number Diff line number Diff line
@@ -2006,6 +2006,39 @@ compute_partial_view(struct drm_i915_gem_object *obj,
	return view;
}

static void set_address_limits(struct vm_area_struct *area,
                              struct i915_vma *vma,
                              unsigned long *start_vaddr,
                              unsigned long *end_vaddr)
{
	unsigned long vm_start, vm_end, vma_size; /* user's memory parameters */
	long start, end; /* memory boundaries */

	/*
	 * Let's move into the ">> PAGE_SHIFT"
	 * domain to be sure not to lose bits
	 */
	vm_start = area->vm_start >> PAGE_SHIFT;
	vm_end = area->vm_end >> PAGE_SHIFT;
	vma_size = vma->size >> PAGE_SHIFT;

	/*
	 * Calculate the memory boundaries by considering the offset
	 * provided by the user during memory mapping and the offset
	 * provided for the partial mapping.
	 */
	start = vm_start;
	start += vma->ggtt_view.partial.offset;
	end = start + vma_size;

	start = max_t(long, start, vm_start);
	end = min_t(long, end, vm_end);

	/* Let's move back into the "<< PAGE_SHIFT" domain */
	*start_vaddr = (unsigned long)start << PAGE_SHIFT;
	*end_vaddr = (unsigned long)end << PAGE_SHIFT;
}

/**
 * i915_gem_fault - fault a page into the GTT
 * @vmf: fault info
@@ -2033,8 +2066,10 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
	struct drm_i915_private *dev_priv = to_i915(dev);
	struct i915_ggtt *ggtt = &dev_priv->ggtt;
	bool write = !!(vmf->flags & FAULT_FLAG_WRITE);
	unsigned long start, end; /* memory boundaries */
	struct i915_vma *vma;
	pgoff_t page_offset;
	unsigned long pfn;
	int ret;

	/* Sanity check that we allow writing into this object */
@@ -2116,12 +2151,14 @@ vm_fault_t i915_gem_fault(struct vm_fault *vmf)
	if (ret)
		goto err_unpin;

	set_address_limits(area, vma, &start, &end);

	pfn = (ggtt->gmadr.start + i915_ggtt_offset(vma)) >> PAGE_SHIFT;
	pfn += (start - area->vm_start) >> PAGE_SHIFT;
	pfn -= vma->ggtt_view.partial.offset;

	/* Finally, remap it using the new GTT offset */
	ret = remap_io_mapping(area,
			       area->vm_start + (vma->ggtt_view.partial.offset << PAGE_SHIFT),
			       (ggtt->gmadr.start + vma->node.start) >> PAGE_SHIFT,
			       min_t(u64, vma->size, area->vm_end - area->vm_start),
			       &ggtt->iomap);
	ret = remap_io_mapping(area, start, pfn, end - start, &ggtt->iomap);
	if (ret)
		goto err_fence;