mirror of
https://github.com/torvalds/linux.git
synced 2026-09-26 10:02:02 +02:00
amd-drm-fixes-7.3-2026-09-24:
amdgpu: - Display ref count fix - Userq fixes - VCN 4, 5 reset fixes - Fixes for various error paths - Stack frame size fixes for various combinations of compilers and configs amdkfd: - Possible UAF fix -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQQgO5Idg2tXNTSZAr293/aFa7yZ2AUCarVdBwAKCRC93/aFa7yZ 2IiRAP9QnDZ0lLR36p0yPHlMVl2opdMfkqeLkdHd6BgDn/3/mwEA780cxI7gxbFH LS7QLSW9L68xjdAixoUWi/UYCIG4sAQ= =VbtV -----END PGP SIGNATURE----- Merge tag 'amd-drm-fixes-7.3-2026-09-24' of https://gitlab.freedesktop.org/drm/amdgpu/kernel into drm-fixes amd-drm-fixes-7.3-2026-09-24: amdgpu: - Display ref count fix - Userq fixes - VCN 4, 5 reset fixes - Fixes for various error paths - Stack frame size fixes for various combinations of compilers and configs amdkfd: - Possible UAF fix Signed-off-by: Dave Airlie <airlied@redhat.com> From: Alex Deucher <alexander.deucher@amd.com> Link: https://patch.msgid.link/20260924172938.634777-1-alexander.deucher@amd.com
This commit is contained in:
commit
0f50dab8b4
|
|
@ -1167,8 +1167,10 @@ int amdgpu_acpi_enumerate_xcc(void)
|
|||
}
|
||||
|
||||
xcc_info = kzalloc_obj(struct amdgpu_acpi_xcc_info);
|
||||
if (!xcc_info)
|
||||
if (!xcc_info) {
|
||||
acpi_dev_put(acpi_dev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&xcc_info->list);
|
||||
xcc_info->handle = acpi_device_handle(acpi_dev);
|
||||
|
|
|
|||
|
|
@ -1780,8 +1780,10 @@ static int amdgpu_debugfs_test_ib_show(struct seq_file *m, void *unused)
|
|||
|
||||
/* Avoid accidently unparking the sched thread during GPU reset */
|
||||
r = down_write_killable(&adev->reset_domain->sem);
|
||||
if (r)
|
||||
if (r) {
|
||||
pm_runtime_put_autosuspend(dev->dev);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* hold on the scheduler */
|
||||
for (i = 0; i < AMDGPU_MAX_RINGS; i++) {
|
||||
|
|
|
|||
|
|
@ -68,6 +68,9 @@ amdgpu_eviction_fence_suspend_worker(struct work_struct *work)
|
|||
|
||||
mutex_lock(&uq_mgr->userq_mutex);
|
||||
|
||||
/* Fence waits are not allowed in a fence signalling critical section. */
|
||||
amdgpu_userq_wait_for_signal(uq_mgr);
|
||||
|
||||
/*
|
||||
* This is intentionally after taking the userq_mutex since we do
|
||||
* allocate memory while holding this lock, but only after ensuring that
|
||||
|
|
|
|||
|
|
@ -254,7 +254,6 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
|
|||
ring->adev = adev;
|
||||
ring->num_hw_submission = sched_hw_submission;
|
||||
ring->sched_score = sched_score;
|
||||
ring->vmid_wait = dma_fence_get_stub();
|
||||
|
||||
ring->idx = adev->num_rings++;
|
||||
adev->rings[ring->idx] = ring;
|
||||
|
|
@ -374,6 +373,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
|
|||
|
||||
ring->max_dw = max_dw;
|
||||
ring->hw_prio = hw_prio;
|
||||
ring->vmid_wait = dma_fence_get_stub();
|
||||
|
||||
if (!ring->no_scheduler && ring->funcs->type < AMDGPU_HW_IP_NUM) {
|
||||
hw_ip = ring->funcs->type;
|
||||
|
|
|
|||
|
|
@ -184,27 +184,27 @@ static void amdgpu_userq_hang_detect_work(struct work_struct *work)
|
|||
void amdgpu_userq_start_hang_detect_work(struct amdgpu_usermode_queue *queue)
|
||||
{
|
||||
struct amdgpu_device *adev;
|
||||
unsigned long timeout_ms;
|
||||
unsigned long timeout_jiffies;
|
||||
|
||||
adev = queue->userq_mgr->adev;
|
||||
/* Determine timeout based on queue type */
|
||||
switch (queue->queue_type) {
|
||||
case AMDGPU_RING_TYPE_GFX:
|
||||
timeout_ms = adev->gfx_timeout;
|
||||
timeout_jiffies = adev->gfx_timeout;
|
||||
break;
|
||||
case AMDGPU_RING_TYPE_COMPUTE:
|
||||
timeout_ms = adev->compute_timeout;
|
||||
timeout_jiffies = adev->compute_timeout;
|
||||
break;
|
||||
case AMDGPU_RING_TYPE_SDMA:
|
||||
timeout_ms = adev->sdma_timeout;
|
||||
timeout_jiffies = adev->sdma_timeout;
|
||||
break;
|
||||
default:
|
||||
timeout_ms = adev->gfx_timeout;
|
||||
timeout_jiffies = adev->gfx_timeout;
|
||||
break;
|
||||
}
|
||||
|
||||
queue_delayed_work(adev->reset_domain->wq, &queue->hang_detect_work,
|
||||
msecs_to_jiffies(timeout_ms));
|
||||
timeout_jiffies);
|
||||
}
|
||||
|
||||
void amdgpu_userq_process_fence_irq(struct amdgpu_device *adev, u32 doorbell)
|
||||
|
|
@ -1272,7 +1272,7 @@ amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr *uq_mgr)
|
||||
{
|
||||
struct amdgpu_usermode_queue *queue;
|
||||
|
|
@ -1291,8 +1291,6 @@ amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr *uq_mgr)
|
|||
void
|
||||
amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr)
|
||||
{
|
||||
/* Wait for any pending userqueue fence work to finish */
|
||||
amdgpu_userq_wait_for_signal(uq_mgr);
|
||||
amdgpu_userq_evict_all(uq_mgr);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@ void amdgpu_userq_mgr_cancel_reset_work(struct amdgpu_device *adev);
|
|||
void amdgpu_userq_mgr_cancel_resume(struct amdgpu_userq_mgr *userq_mgr);
|
||||
void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr);
|
||||
|
||||
void amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr *uq_mgr);
|
||||
void amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr);
|
||||
|
||||
void amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *userq_mgr,
|
||||
|
|
|
|||
|
|
@ -2678,6 +2678,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
|||
amdgpu_bo_unref(&root_bo);
|
||||
|
||||
error_free_delayed:
|
||||
dma_fence_put(vm->last_update);
|
||||
dma_fence_put(vm->last_tlb_flush);
|
||||
dma_fence_put(vm->last_unlocked);
|
||||
ttm_lru_bulk_move_fini(&adev->mman.bdev, &vm->lru_bulk_move);
|
||||
|
|
|
|||
|
|
@ -1689,7 +1689,8 @@ static int vcn_v4_0_3_reset_jpeg_pre_helper(struct amdgpu_device *adev, int inst
|
|||
/* if Jobs are still pending after timeout,
|
||||
* We'll handle them in the bottom helper
|
||||
*/
|
||||
amdgpu_fence_wait_polling(ring, wait_seq, adev->video_timeout);
|
||||
amdgpu_fence_wait_polling(ring, wait_seq,
|
||||
jiffies_to_usecs(adev->video_timeout));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1335,7 +1335,8 @@ static int vcn_v5_0_1_reset_jpeg_pre_helper(struct amdgpu_device *adev, int inst
|
|||
/* if Jobs are still pending after timeout,
|
||||
* We'll handle them in the bottom helper
|
||||
*/
|
||||
amdgpu_fence_wait_polling(ring, wait_seq, adev->video_timeout);
|
||||
amdgpu_fence_wait_polling(ring, wait_seq,
|
||||
jiffies_to_usecs(adev->video_timeout));
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@
|
|||
#include <linux/time.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mman.h>
|
||||
#include <linux/pseudo_fs.h>
|
||||
#include <linux/ptrace.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/processor.h>
|
||||
|
|
@ -70,18 +71,54 @@ static const struct class kfd_class = {
|
|||
};
|
||||
|
||||
/*
|
||||
* Cache the address space of the chardev on first open so that the reset
|
||||
* path can drop all userspace mappings of doorbell and MMIO ranges via
|
||||
* unmap_mapping_range().
|
||||
* Private pseudo-filesystem for KFD, Provides a stable, module-owned
|
||||
* inode whose address_space is the unmap target for all /dev/kfd
|
||||
* openers during GPU reset.
|
||||
*/
|
||||
static struct address_space *kfd_dev_mapping;
|
||||
static struct vfsmount *kfd_fs_mnt;
|
||||
static int kfd_fs_cnt;
|
||||
|
||||
static int kfd_fs_init_fs_context(struct fs_context *fc)
|
||||
{
|
||||
return init_pseudo(fc, 0x4b464400 /* "KFD" */) ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
static struct file_system_type kfd_fs_type = {
|
||||
.name = "kfd",
|
||||
.init_fs_context = kfd_fs_init_fs_context,
|
||||
.kill_sb = kill_anon_super,
|
||||
};
|
||||
|
||||
static struct inode *kfd_fs_inode_new(void)
|
||||
{
|
||||
struct inode *inode;
|
||||
int r;
|
||||
|
||||
r = simple_pin_fs(&kfd_fs_type, &kfd_fs_mnt, &kfd_fs_cnt);
|
||||
if (r < 0)
|
||||
return ERR_PTR(r);
|
||||
|
||||
inode = alloc_anon_inode(kfd_fs_mnt->mnt_sb);
|
||||
if (IS_ERR(inode))
|
||||
simple_release_fs(&kfd_fs_mnt, &kfd_fs_cnt);
|
||||
|
||||
return inode;
|
||||
}
|
||||
|
||||
static void kfd_fs_inode_free(struct inode *inode)
|
||||
{
|
||||
if (inode) {
|
||||
iput(inode);
|
||||
simple_release_fs(&kfd_fs_mnt, &kfd_fs_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
static struct inode *kfd_anon_inode;
|
||||
|
||||
void kfd_dev_unmap_mapping_range(loff_t const holebegin, loff_t const holelen)
|
||||
{
|
||||
struct address_space *mapping = READ_ONCE(kfd_dev_mapping);
|
||||
|
||||
if (mapping)
|
||||
unmap_mapping_range(mapping, holebegin, holelen, 1);
|
||||
if (kfd_anon_inode)
|
||||
unmap_mapping_range(kfd_anon_inode->i_mapping, holebegin, holelen, 1);
|
||||
}
|
||||
|
||||
static inline struct kfd_process_device *kfd_lock_pdd_by_id(struct kfd_process *p, __u32 gpu_id)
|
||||
|
|
@ -107,6 +144,13 @@ int kfd_chardev_init(void)
|
|||
{
|
||||
int err = 0;
|
||||
|
||||
kfd_anon_inode = kfd_fs_inode_new();
|
||||
if (IS_ERR(kfd_anon_inode)) {
|
||||
err = PTR_ERR(kfd_anon_inode);
|
||||
kfd_anon_inode = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
kfd_char_dev_major = register_chrdev(0, kfd_dev_name, &kfd_fops);
|
||||
err = kfd_char_dev_major;
|
||||
if (err < 0)
|
||||
|
|
@ -130,6 +174,8 @@ int kfd_chardev_init(void)
|
|||
err_class_create:
|
||||
unregister_chrdev(kfd_char_dev_major, kfd_dev_name);
|
||||
err_register_chrdev:
|
||||
kfd_fs_inode_free(kfd_anon_inode);
|
||||
kfd_anon_inode = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
|
|
@ -138,6 +184,8 @@ void kfd_chardev_exit(void)
|
|||
device_destroy(&kfd_class, MKDEV(kfd_char_dev_major, 0));
|
||||
class_unregister(&kfd_class);
|
||||
unregister_chrdev(kfd_char_dev_major, kfd_dev_name);
|
||||
kfd_fs_inode_free(kfd_anon_inode);
|
||||
kfd_anon_inode = NULL;
|
||||
kfd_device = NULL;
|
||||
}
|
||||
|
||||
|
|
@ -150,12 +198,7 @@ static int kfd_open(struct inode *inode, struct file *filep)
|
|||
if (iminor(inode) != 0)
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
* /dev/kfd is a single chardev so all opens share one inode. Cache
|
||||
* its address_space on the first open for use by the reset path.
|
||||
*/
|
||||
if (!READ_ONCE(kfd_dev_mapping))
|
||||
cmpxchg(&kfd_dev_mapping, NULL, inode->i_mapping);
|
||||
filep->f_mapping = kfd_anon_inode->i_mapping;
|
||||
|
||||
is_32bit_user_mode = in_compat_syscall();
|
||||
|
||||
|
|
|
|||
|
|
@ -5583,8 +5583,10 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm,
|
|||
|
||||
skip_modeset:
|
||||
/* Release extra reference */
|
||||
if (new_stream)
|
||||
if (new_stream) {
|
||||
dc_stream_release(new_stream);
|
||||
new_stream = NULL;
|
||||
}
|
||||
new_stream = NULL;
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -29,14 +29,14 @@ dml_ccflags := $(CC_FLAGS_FPU)
|
|||
dml_rcflags := $(CC_FLAGS_NO_FPU)
|
||||
|
||||
ifneq ($(CONFIG_FRAME_WARN),0)
|
||||
ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y)
|
||||
ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)$(CONFIG_UBSAN)),y)
|
||||
ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_COMPILE_TEST),yy)
|
||||
frame_warn_limit := 4096
|
||||
else
|
||||
frame_warn_limit := 3072
|
||||
endif
|
||||
else
|
||||
frame_warn_limit := 2048
|
||||
frame_warn_limit := 3072
|
||||
endif
|
||||
|
||||
ifeq ($(call test-lt, $(CONFIG_FRAME_WARN), $(frame_warn_limit)),y)
|
||||
|
|
|
|||
|
|
@ -28,14 +28,14 @@ dml2_ccflags := $(CC_FLAGS_FPU)
|
|||
dml2_rcflags := $(CC_FLAGS_NO_FPU)
|
||||
|
||||
ifneq ($(CONFIG_FRAME_WARN),0)
|
||||
ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)),y)
|
||||
ifeq ($(filter y,$(CONFIG_KASAN)$(CONFIG_KCSAN)$(CONFIG_UBSAN)),y)
|
||||
ifeq ($(CONFIG_CC_IS_CLANG)$(CONFIG_COMPILE_TEST),yy)
|
||||
frame_warn_limit := 4096
|
||||
else
|
||||
frame_warn_limit := 3072
|
||||
endif
|
||||
else
|
||||
frame_warn_limit := 2056
|
||||
frame_warn_limit := 3072
|
||||
endif
|
||||
|
||||
ifeq ($(call test-lt, $(CONFIG_FRAME_WARN), $(frame_warn_limit)),y)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user