From c9198633ac9eb5b23951585bca6b950b2ddf23c4 Mon Sep 17 00:00:00 2001 From: Nikhil V Date: Wed, 20 Aug 2025 18:30:23 +0530 Subject: [PATCH] ANDROID: gunyah: Fix the issue with gunyah_cma_release Currently, gunyah_cma_release() unconditionally releases the entire CMA memory region of the VM, regardless of how much was actually mapped. This can lead to issues if AVF clients lauches VM wherein the memory mapped is less than the size of the VM's CMA region(max size). To address this: - A new mapped_size field is added to struct gunyah_cma to track the actual size mapped. - gunyah_cma_alloc() sets this field and logs a debug message if the mapped size is less than the max size. - gunyah_cma_release() now uses mapped_size to determine how much memory to release. Bug: 440480668 Change-Id: I6408c91eedb4cfe911a52c8a8a8734892e49e209 Signed-off-by: Nikhil V --- drivers/virt/gunyah/vm_mgr_cma_mem.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/virt/gunyah/vm_mgr_cma_mem.c b/drivers/virt/gunyah/vm_mgr_cma_mem.c index 7a7dc2a84f13..1de6c1bdb1fd 100644 --- a/drivers/virt/gunyah/vm_mgr_cma_mem.c +++ b/drivers/virt/gunyah/vm_mgr_cma_mem.c @@ -19,7 +19,8 @@ struct gunyah_cma { struct page *page; struct miscdevice miscdev; struct list_head list; - unsigned long size; + unsigned long max_size; + unsigned long mapped_size; }; struct gunyah_cma_parent { @@ -55,14 +56,19 @@ static int gunyah_cma_alloc(struct gunyah_cma *cma, loff_t len) if (!cma->page) return -ENOMEM; + if (len < max_size) + dev_dbg(&cma->dev, "client mapped %lld bytes, less than max %lld bytes\n", + len, max_size); + + cma->mapped_size = len; + return 0; } static int gunyah_cma_release(struct inode *inode, struct file *file) { struct gunyah_cma *cma = file->private_data; - loff_t max_size = i_size_read(file_inode(cma->file)); - unsigned int count = PAGE_ALIGN(max_size) >> PAGE_SHIFT; + unsigned int count = PAGE_ALIGN(cma->mapped_size) >> PAGE_SHIFT; if (!cma->page) return 0; @@ -278,7 +284,7 @@ static long gunyah_cma_create_mem_fd(struct gunyah_cma *cma) inode = file->f_inode; inode->i_mode |= S_IFREG; /* Platform specific size of CMA per VM */ - i_size_write(inode, cma->size); + i_size_write(inode, cma->max_size); file->f_flags |= O_LARGEFILE; file->f_mapping = inode->i_mapping; @@ -393,7 +399,7 @@ static int gunyah_cma_probe(struct platform_device *pdev) dev_err(dev, "Failed to find reserved memory for %s\n", mem_name[i]); goto err_device; } - cma->size = rmem->size; + cma->max_size = rmem->size; cma->page = NULL; list_add(&cma->list, &pcma->gunyah_cma_children); dev_dbg(dev, "Created a reserved cma pool for %s\n", mem_name[i]);