diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf.c b/drivers/gpu/arm/valhall/csf/mali_kbase_csf.c index 26ebe40690cc..22214f5b95e7 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf.c +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf.c @@ -211,11 +211,6 @@ static void kernel_free_user_io_pages(struct kbase_context *kctx, struct tagged_ kbase_gpu_vm_lock(kctx); vunmap(user_io_addr); - if (kctx->csf.user_io.vma != NULL) { - zap_vma_ptes(kctx->csf.user_io.vma, kctx->csf.user_io.vma->vm_start, - KBASEP_NUM_CS_USER_IO_PAGES * PAGE_SIZE); - kctx->csf.user_io.vma = NULL; - } WARN_ON(atomic_read(&kctx->permanent_mapped_pages) < KBASEP_NUM_CS_USER_IO_PAGES); atomic_sub(KBASEP_NUM_CS_USER_IO_PAGES, &kctx->permanent_mapped_pages); @@ -1028,6 +1023,13 @@ static void unbind_stopped_queue(struct kbase_context *kctx, struct kbase_queue queue->group = NULL; kbase_csf_scheduler_spin_unlock(kctx->kbdev, flags); + /* Ensure that the user I/O pages are no longer accessible */ + mutex_lock(&kctx->kbdev->csf.reg_lock); + unmap_mapping_range(kctx->kbdev->csf.db_filp->f_inode->i_mapping, + (loff_t)(queue->db_file_offset << PAGE_SHIFT), + BASEP_QUEUE_NR_MMAP_USER_PAGES * PAGE_SIZE, 1); + mutex_unlock(&kctx->kbdev->csf.reg_lock); + put_user_pages_mmap_handle(kctx, queue); WARN_ON_ONCE(queue->doorbell_nr != KBASEP_USER_DB_NR_INVALID); queue->bind_state = KBASE_CSF_QUEUE_UNBOUND; diff --git a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_defs.h b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_defs.h index 16741079cb36..48569836e320 100644 --- a/drivers/gpu/arm/valhall/csf/mali_kbase_csf_defs.h +++ b/drivers/gpu/arm/valhall/csf/mali_kbase_csf_defs.h @@ -927,17 +927,6 @@ struct kbase_csf_event { spinlock_t lock; }; -/** - * struct kbase_csf_user_io_context - Object containing members to manage the mapping - * of USER io page for a context. - * - * @vma: Pointer to the VMA corresponding to the virtual mapping - * of the USER io page. - */ -struct kbase_csf_user_io_context { - struct vm_area_struct *vma; -}; - /** * struct kbase_csf_user_reg_context - Object containing members to manage the mapping * of USER Register page for a context. @@ -997,7 +986,6 @@ struct kbase_csf_user_reg_context { * @cpu_queue: CPU queue information. Only be available when DEBUG_FS * is enabled. * @user_reg: Collective information to support mapping to USER Register page. - * @user_io: Collective information to support mapping to USER IO page. * @pending_sync_update: Indicates that kbase_csf_scheduler_kthread() should * handle SYNC_UPDATE event for this context. This would * be set to false when the work is done. This is used @@ -1018,7 +1006,6 @@ struct kbase_csf_context { struct kbase_csf_scheduler_context sched; struct kbase_csf_cpu_queue_context cpu_queue; struct kbase_csf_user_reg_context user_reg; - struct kbase_csf_user_io_context user_io; atomic_t pending_sync_update; }; diff --git a/drivers/gpu/arm/valhall/mali_kbase_mem_linux.c b/drivers/gpu/arm/valhall/mali_kbase_mem_linux.c index d7301653788e..c8e36707aae9 100644 --- a/drivers/gpu/arm/valhall/mali_kbase_mem_linux.c +++ b/drivers/gpu/arm/valhall/mali_kbase_mem_linux.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note /* * - * (C) COPYRIGHT 2010-2024 ARM Limited. All rights reserved. + * (C) COPYRIGHT 2010-2025 ARM Limited. All rights reserved. * * This program is free software and is provided to you under the terms of the * GNU General Public License version 2 as published by the Free Software @@ -3440,13 +3440,19 @@ static vm_fault_t kbase_csf_user_io_pages_vm_fault(struct vm_fault *vmf) output_cpu_addr = input_cpu_addr + PAGE_SIZE; if (mali_kbase_supports_csg_cs_user_page_allocation(queue->kctx->api_version)) { - if (!queue->group) { - ret = VM_FAULT_SIGBUS; - goto exit; + if (likely(queue->group)) { + input_page_pfn = PFN_DOWN(as_phys_addr_t(queue->group->phys[0])); + output_page_pfn = PFN_DOWN(as_phys_addr_t(queue->group->phys[1])); + } else { + /* This could happen if userspace tries to access this memory + * after the group has already been terminated due to a fault. + * Re-map to the dummy page to render the access harmless. + */ + input_page_pfn = + PFN_DOWN(as_phys_addr_t(kbdev->csf.user_reg.dummy_page)); + output_page_pfn = + PFN_DOWN(as_phys_addr_t(kbdev->csf.user_reg.dummy_page)); } - - input_page_pfn = PFN_DOWN(as_phys_addr_t(queue->group->phys[0])); - output_page_pfn = PFN_DOWN(as_phys_addr_t(queue->group->phys[1])); } else { input_page_pfn = PFN_DOWN(as_phys_addr_t(queue->phys[0])); output_page_pfn = PFN_DOWN(as_phys_addr_t(queue->phys[1])); @@ -3541,7 +3547,6 @@ static int kbase_csf_cpu_mmap_user_io_pages(struct kbase_context *kctx, struct v get_file(vma->vm_file); /* Also adjust the vm_pgoff */ vma->vm_pgoff = queue->db_file_offset; - kctx->csf.user_io.vma = vma; return 0;