summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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;
}