summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/amdgpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/amdgpu')
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c77
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c13
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mes_userqueue.c9
6 files changed, 79 insertions, 50 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
index 054870e9078d..ca5860e493a6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c
@@ -598,14 +598,18 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,
/* first get metadata_size by buffer = NULL */
r = amdgpu_bo_get_metadata(bo, NULL, 0,
metadata_size, NULL);
+ if (r)
+ goto out_put;
/* user buf_size is bigger than bo metadata_size
* allocate a buf at kernel space and copy */
if (*metadata_size <= buffer_size) {
*metadata_buffer = kzalloc(*metadata_size, GFP_KERNEL);
- if (!*metadata_buffer)
- return -ENOMEM;
+ if (!*metadata_buffer) {
+ r = -ENOMEM;
+ goto out_put;
+ }
r = amdgpu_bo_get_metadata(bo, *metadata_buffer, *metadata_size,
NULL, &metadata_flags);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
index aca1a8045afa..ab7ccfaea22a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -121,6 +121,20 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f,
*pos &= (1UL << 22) - 1;
+ if (size > PAGE_SIZE)
+ return -EINVAL;
+
+ /*
+ * Access the user buffer only while none of the locks below are held:
+ * a fault takes mmap_lock, and grbm_idx_mutex and srbm_mutex nest
+ * inside it.
+ */
+ u32 *data __free(kfree) = kmalloc(size, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ if (!read && copy_from_user(data, buf, size))
+ return -EFAULT;
+
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
if (r < 0) {
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@ -152,28 +166,16 @@ static int amdgpu_debugfs_process_reg_op(bool read, struct file *f,
mutex_lock(&adev->pm.mutex);
while (size) {
- uint32_t value;
-
- if (read) {
- value = RREG32(*pos >> 2);
- r = put_user(value, (uint32_t *)buf);
- } else {
- r = get_user(value, (uint32_t *)buf);
- if (!r)
- amdgpu_mm_wreg_mmio_rlc(adev, *pos >> 2, value, 0);
- }
- if (r) {
- result = r;
- goto end;
- }
+ if (read)
+ data[result >> 2] = RREG32(*pos >> 2);
+ else
+ amdgpu_mm_wreg_mmio_rlc(adev, *pos >> 2, data[result >> 2], 0);
result += 4;
- buf += 4;
*pos += 4;
size -= 4;
}
-end:
if (use_bank) {
amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0);
mutex_unlock(&adev->grbm_idx_mutex);
@@ -188,6 +190,10 @@ end:
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
amdgpu_virt_disable_access_debugfs(adev);
+
+ if (read && copy_to_user(buf, data, result))
+ return -EFAULT;
+
return result;
}
@@ -238,11 +244,24 @@ static ssize_t amdgpu_debugfs_regs2_op(struct file *f, char __user *buf, u32 off
struct amdgpu_device *adev = rd->adev;
ssize_t result = 0;
int r;
- uint32_t value;
if (size & 0x3 || offset & 0x3)
return -EINVAL;
+ if (size > PAGE_SIZE)
+ return -EINVAL;
+
+ /*
+ * Access the user buffer only while none of the locks below are held:
+ * a fault takes mmap_lock, and grbm_idx_mutex and srbm_mutex nest
+ * inside it.
+ */
+ u32 *data __free(kfree) = kmalloc(size, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ if (write_en && copy_from_user(data, buf, size))
+ return -EFAULT;
+
r = pm_runtime_get_sync(adev_to_drm(adev)->dev);
if (r < 0) {
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
@@ -281,24 +300,16 @@ static ssize_t amdgpu_debugfs_regs2_op(struct file *f, char __user *buf, u32 off
mutex_lock(&adev->pm.mutex);
while (size) {
- if (!write_en) {
- value = RREG32(offset >> 2);
- r = put_user(value, (uint32_t *)buf);
- } else {
- r = get_user(value, (uint32_t *)buf);
- if (!r)
- amdgpu_mm_wreg_mmio_rlc(adev, offset >> 2, value, rd->id.xcc_id);
- }
- if (r) {
- result = r;
- goto end;
- }
+ if (!write_en)
+ data[result >> 2] = RREG32(offset >> 2);
+ else
+ amdgpu_mm_wreg_mmio_rlc(adev, offset >> 2, data[result >> 2],
+ rd->id.xcc_id);
offset += 4;
size -= 4;
result += 4;
- buf += 4;
}
-end:
+
if (rd->id.use_grbm) {
amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, rd->id.xcc_id);
mutex_unlock(&adev->grbm_idx_mutex);
@@ -317,6 +328,10 @@ end:
pm_runtime_put_autosuspend(adev_to_drm(adev)->dev);
amdgpu_virt_disable_access_debugfs(adev);
+
+ if (!write_en && copy_to_user(buf, data, result))
+ return -EFAULT;
+
return result;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
index 3dc8faa091d7..61dc2a6be7e7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
@@ -1080,20 +1080,17 @@ void amdgpu_gmc_init_vga_resv_regions(struct amdgpu_device *adev)
case CHIP_RENOIR:
adev->mman.keep_stolen_vga_memory = true;
break;
- case CHIP_POLARIS10:
- case CHIP_POLARIS11:
- case CHIP_POLARIS12:
- /* MacBookPros with switchable graphics put VRAM at 0 when
- * the iGPU is enabled which results in cursor issues if
- * the cursor ends up at 0. Reserve vram at 0 in that case.
- */
- if (adev->gmc.vram_start == 0)
- adev->mman.keep_stolen_vga_memory = true;
- break;
default:
adev->mman.keep_stolen_vga_memory = false;
break;
}
+ /* MacBookPros with switchable graphics put VRAM at 0 when
+ * the iGPU is enabled which results in cursor issues if
+ * the cursor ends up at 0. Reserve vram at 0 in that case.
+ */
+ if ((adev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) &&
+ (adev->gmc.vram_start == 0))
+ adev->mman.keep_stolen_vga_memory = true;
if (amdgpu_sriov_vf(adev) ||
!amdgpu_device_has_display_hardware(adev)) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 242c48e85912..7c081b338fe2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -30,6 +30,7 @@
#include <drm/amdgpu_drm.h>
#include <drm/drm_drv.h>
#include <drm/drm_fb_helper.h>
+#include <drm/drm_vblank.h>
#include "amdgpu_uvd.h"
#include "amdgpu_vce.h"
#include "atom.h"
@@ -1660,6 +1661,9 @@ u32 amdgpu_get_vblank_counter_kms(struct drm_crtc *crtc)
DRM_ERROR("Invalid crtc %u\n", pipe);
return -EINVAL;
}
+ if (!down_read_trylock(&adev->reset_domain->sem))
+ return drm_crtc_vblank_count(crtc);
+
/* The hw increments its frame counter at start of vsync, not at start
* of vblank, as is required by DRM core vblank counter handling.
@@ -1705,6 +1709,7 @@ u32 amdgpu_get_vblank_counter_kms(struct drm_crtc *crtc)
DRM_DEBUG_VBL("NULL mode info! Returned count may be wrong.\n");
}
+ up_read(&adev->reset_domain->sem);
return count;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
index cc8e7af18834..9316423f9340 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -472,6 +472,7 @@ amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
u64 doorbell_index;
struct drm_gem_object *gobj;
struct amdgpu_userq_obj *db_obj = db_info->db_obj;
+ struct amdgpu_bo *abo;
int r, db_size;
gobj = drm_gem_object_lookup(filp, db_info->doorbell_handle);
@@ -480,7 +481,17 @@ amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
return -EINVAL;
}
- db_obj->obj = amdgpu_bo_ref(gem_to_amdgpu_bo(gobj));
+ /*
+ * Pinning a regular BO into the doorbell domain would discard its
+ * contents, possibly those of a buffer shared by another client.
+ */
+ abo = gem_to_amdgpu_bo(gobj);
+ if (!(abo->preferred_domains & AMDGPU_GEM_DOMAIN_DOORBELL)) {
+ drm_gem_object_put(gobj);
+ return -EINVAL;
+ }
+
+ db_obj->obj = amdgpu_bo_ref(abo);
drm_gem_object_put(gobj);
r = amdgpu_bo_reserve(db_obj->obj, true);
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
index 14a5abe42d1f..8d5dcaf4fea6 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
@@ -361,8 +361,7 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
compute_mqd = memdup_user(u64_to_user_ptr(mqd_user->mqd), mqd_user->mqd_size);
if (IS_ERR(compute_mqd)) {
- DRM_ERROR("Failed to read user MQD\n");
- r = -ENOMEM;
+ r = PTR_ERR(compute_mqd);
goto free_mqd;
}
@@ -406,8 +405,7 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
mqd_gfx_v11 = memdup_user(u64_to_user_ptr(mqd_user->mqd), mqd_user->mqd_size);
if (IS_ERR(mqd_gfx_v11)) {
- DRM_ERROR("Failed to read user MQD\n");
- r = -ENOMEM;
+ r = PTR_ERR(mqd_gfx_v11);
goto free_mqd;
}
@@ -451,8 +449,7 @@ static int mes_userq_mqd_create(struct amdgpu_usermode_queue *queue,
mqd_sdma_v11 = memdup_user(u64_to_user_ptr(mqd_user->mqd), mqd_user->mqd_size);
if (IS_ERR(mqd_sdma_v11)) {
- DRM_ERROR("Failed to read sdma user MQD\n");
- r = -ENOMEM;
+ r = PTR_ERR(mqd_sdma_v11);
goto free_mqd;
}