summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhang Jiejing <jiejing.zhang@freescale.com>2012-07-09 12:59:12 +0800
committerZhang Jiejing <jiejing.zhang@freescale.com>2012-07-10 11:21:20 +0800
commit88d009f005790e5f46c96788409f403cff0a74c9 (patch)
tree52e5a2f18080ae882a86021a7b5820b0df6356de
parent0e8426c3daeb634b093a0a3791fe04764a090dc1 (diff)
ENGR00216013-4 vpu: add phy address check ioctl.
this patch is adding a ioctl for vpu to check the phy addr before vpu start using this addr, this use case is common in some Direct Render case, the VPU 's framebuffer phy memory is allocate by GPU, if the address given by GPU have some wrong, like pass a virtual address, vpu will hang the system. Add this IOCTL to be the goalkeeper, this IOCTL can check whether the phy address was virtual memory or the address is within phy memory of your DDR. The phy memory valild check is now doing best effort: 1. check whether is was allocated by vmalloc(), which must be a phy un-continus 2. check whether is was beyound DDR's top address, usually the other driver pass a virtual address as a phy address. Signed-off-by: Zhang Jiejing <jiejing.zhang@freescale.com>
-rw-r--r--drivers/mxc/vpu/mxc_vpu.c57
1 files changed, 57 insertions, 0 deletions
diff --git a/drivers/mxc/vpu/mxc_vpu.c b/drivers/mxc/vpu/mxc_vpu.c
index c3235dfb361e..4574208fefb8 100644
--- a/drivers/mxc/vpu/mxc_vpu.c
+++ b/drivers/mxc/vpu/mxc_vpu.c
@@ -39,6 +39,12 @@
#include <linux/workqueue.h>
#include <linux/sched.h>
#include <linux/vmalloc.h>
+#include <linux/page-flags.h>
+#include <linux/mm_types.h>
+#include <linux/types.h>
+#include <linux/memblock.h>
+#include <linux/memory.h>
+#include <asm/page.h>
#include <asm/sizes.h>
#include <mach/clock.h>
#include <mach/hardware.h>
@@ -84,6 +90,7 @@ static struct vpu_mem_desc vshare_mem = { 0 };
static void __iomem *vpu_base;
static int vpu_ipi_irq;
static u32 phy_vpu_base_addr;
+static phys_addr_t top_address_DRAM;
static struct mxc_vpu_platform_data *vpu_plat;
/* IRAM setting */
@@ -218,6 +225,24 @@ static irqreturn_t vpu_jpu_irq_handler(int irq, void *dev_id)
#endif
/*!
+ * @brief check phy memory prepare to pass to vpu is valid or not, we
+ * already address some issue that if pass a wrong address to vpu
+ * (like virtual address), system will hang.
+ *
+ * @return true return is a valid phy memory address, false return not.
+ */
+bool vpu_is_valid_phy_memory(u32 vaddr, u32 paddr, u32 size)
+{
+ if (virt_addr_valid((void *)vaddr) && is_vmalloc_addr((void *)vaddr))
+ return false;
+
+ if (paddr > top_address_DRAM)
+ return false;
+
+ return true;
+}
+
+/*!
* @brief open function for vpu file operation
*
* @return 0 on success or negative error code on error
@@ -466,6 +491,34 @@ static long vpu_ioctl(struct file *filp, u_int cmd,
break;
case VPU_IOC_PHYMEM_DUMP:
break;
+ case VPU_IOC_PHYMEM_CHECK:
+ {
+ struct vpu_mem_desc check_memory;
+ ret = copy_from_user(&check_memory,
+ (void __user *)arg,
+ sizeof(struct vpu_mem_desc));
+ if (ret != 0) {
+ printk(KERN_ERR "copy from user failure:%d\n", ret);
+ ret = -EFAULT;
+ break;
+ }
+ check_memory.virt_uaddr = (u32)__va(check_memory.phy_addr);
+ ret = vpu_is_valid_phy_memory((u32)check_memory.virt_uaddr,
+ (u32)check_memory.phy_addr,
+ check_memory.size);
+ pr_debug("vpu: memory phy:0x%x va:0x%x %s phy memory\n",
+ check_memory.phy_addr, check_memory.virt_uaddr,
+ (ret ? "is" : "isn't"));
+ /* borrow .size to pass back the result. */
+ check_memory.size = ret;
+ ret = copy_to_user((void __user *)arg, &check_memory,
+ sizeof(struct vpu_mem_desc));
+ if (ret) {
+ ret = -EFAULT;
+ break;
+ }
+ break;
+ }
default:
{
printk(KERN_ERR "No such IOCTL, cmd is %d\n", cmd);
@@ -844,6 +897,10 @@ static int __init vpu_init(void)
init_waitqueue_head(&vpu_queue);
+
+ memblock_analyze();
+ top_address_DRAM = memblock_end_of_DRAM_with_reserved();
+
return ret;
}