]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00216013-4 vpu: add phy address check ioctl.
authorZhang Jiejing <jiejing.zhang@freescale.com>
Mon, 16 Jul 2012 05:53:26 +0000 (13:53 +0800)
committerOliver Wendt <ow@karo-electronics.de>
Mon, 30 Sep 2013 12:12:24 +0000 (14:12 +0200)
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>
drivers/mxc/vpu/mxc_vpu.c

index c97437fb0c9e571670e41b6d3f07a52225e0015d..0d36a25d885044ea2f98b98d69d41a3c13a72de3 100644 (file)
 #include <linux/sched.h>
 #include <linux/vmalloc.h>
 #include <linux/regulator/consumer.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>
@@ -85,6 +91,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,21 @@ 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 paddr)
+{
+       if (paddr > top_address_DRAM)
+               return false;
+
+       return true;
+}
+
 /*!
  * @brief open function for vpu file operation
  *
@@ -478,6 +500,31 @@ 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;
+               }
+               ret = vpu_is_valid_phy_memory((u32)check_memory.phy_addr);
+
+               pr_debug("vpu: memory phy:0x%x %s phy memory\n",
+                      check_memory.phy_addr, (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);
@@ -867,6 +914,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;
 }