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

Commit cc9e67e3 authored by Christian König's avatar Christian König Committed by Alex Deucher
Browse files

drm/radeon: fix VM IB handling



Calling radeon_vm_bo_find on the IB BO during CS
is illegal and can lead to an crash.

Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 036bf46a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -879,6 +879,8 @@ struct radeon_vm {
	/* array of page tables, one for each page directory entry */
	struct radeon_vm_pt		*page_tables;

	struct radeon_bo_va		*ib_bo_va;

	struct mutex			mutex;
	/* last fence for cs using this vm */
	struct radeon_fence		*fence;
+3 −3
Original line number Diff line number Diff line
@@ -472,13 +472,13 @@ static int radeon_bo_vm_update_pte(struct radeon_cs_parser *p,
	if (r)
		return r;

	bo_va = radeon_vm_bo_find(vm, rdev->ring_tmp_bo.bo);
	if (bo_va == NULL) {
	if (vm->ib_bo_va == NULL) {
		DRM_ERROR("Tmp BO not in VM!\n");
		return -EINVAL;
	}

	r = radeon_vm_bo_update(rdev, bo_va, &rdev->ring_tmp_bo.bo->tbo.mem);
	r = radeon_vm_bo_update(rdev, vm->ib_bo_va,
				&rdev->ring_tmp_bo.bo->tbo.mem);
	if (r)
		return r;

+13 −13
Original line number Diff line number Diff line
@@ -579,7 +579,7 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
	/* new gpu have virtual address space support */
	if (rdev->family >= CHIP_CAYMAN) {
		struct radeon_fpriv *fpriv;
		struct radeon_bo_va *bo_va;
		struct radeon_vm *vm;
		int r;

		fpriv = kzalloc(sizeof(*fpriv), GFP_KERNEL);
@@ -587,7 +587,8 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
			return -ENOMEM;
		}

		r = radeon_vm_init(rdev, &fpriv->vm);
		vm = &fpriv->vm;
		r = radeon_vm_init(rdev, vm);
		if (r) {
			kfree(fpriv);
			return r;
@@ -596,22 +597,23 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
		if (rdev->accel_working) {
			r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
			if (r) {
				radeon_vm_fini(rdev, &fpriv->vm);
				radeon_vm_fini(rdev, vm);
				kfree(fpriv);
				return r;
			}

			/* map the ib pool buffer read only into
			 * virtual address space */
			bo_va = radeon_vm_bo_add(rdev, &fpriv->vm,
			vm->ib_bo_va = radeon_vm_bo_add(rdev, vm,
							rdev->ring_tmp_bo.bo);
			r = radeon_vm_bo_set_addr(rdev, bo_va, RADEON_VA_IB_OFFSET,
			r = radeon_vm_bo_set_addr(rdev, vm->ib_bo_va,
						  RADEON_VA_IB_OFFSET,
						  RADEON_VM_PAGE_READABLE |
						  RADEON_VM_PAGE_SNOOPED);

			radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
			if (r) {
				radeon_vm_fini(rdev, &fpriv->vm);
				radeon_vm_fini(rdev, vm);
				kfree(fpriv);
				return r;
			}
@@ -640,21 +642,19 @@ void radeon_driver_postclose_kms(struct drm_device *dev,
	/* new gpu have virtual address space support */
	if (rdev->family >= CHIP_CAYMAN && file_priv->driver_priv) {
		struct radeon_fpriv *fpriv = file_priv->driver_priv;
		struct radeon_bo_va *bo_va;
		struct radeon_vm *vm = &fpriv->vm;
		int r;

		if (rdev->accel_working) {
			r = radeon_bo_reserve(rdev->ring_tmp_bo.bo, false);
			if (!r) {
				bo_va = radeon_vm_bo_find(&fpriv->vm,
							  rdev->ring_tmp_bo.bo);
				if (bo_va)
					radeon_vm_bo_rmv(rdev, bo_va);
				if (vm->ib_bo_va)
					radeon_vm_bo_rmv(rdev, vm->ib_bo_va);
				radeon_bo_unreserve(rdev->ring_tmp_bo.bo);
			}
		}

		radeon_vm_fini(rdev, &fpriv->vm);
		radeon_vm_fini(rdev, vm);
		kfree(fpriv);
		file_priv->driver_priv = NULL;
	}
+1 −0
Original line number Diff line number Diff line
@@ -1007,6 +1007,7 @@ int radeon_vm_init(struct radeon_device *rdev, struct radeon_vm *vm)
	int r;

	vm->id = 0;
	vm->ib_bo_va = NULL;
	vm->fence = NULL;
	vm->last_flush = NULL;
	vm->last_id_use = NULL;