summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpopcornmix <popcornmix@gmail.com>2015-05-19 18:49:06 +0100
committerpopcornmix <popcornmix@gmail.com>2015-05-23 18:13:32 +0100
commitef724874a73fdecf9bcb98d7124ea751a9203891 (patch)
treef3e6e65d810a70e7da5d50ffbdd609c2a8faba96
parentb4eeb0d67525bf007598359c6cc57b22ea3cefd3 (diff)
downloadlinux-ef724874a73fdecf9bcb98d7124ea751a9203891.tar.gz
vcsm: Add ioctl for custom cache flushing
-rw-r--r--arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h15
-rw-r--r--drivers/char/broadcom/vc_sm/vmcs_sm.c49
2 files changed, 64 insertions, 0 deletions
diff --git a/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h b/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h
index 42d0eb09ee36..334f36d0d697 100644
--- a/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h
+++ b/arch/arm/mach-bcm2708/include/mach/vmcs_sm_ioctl.h
@@ -61,6 +61,8 @@ enum vmcs_sm_cmd_e {
VMCS_SM_CMD_HOST_WALK_PID_ALLOC,
VMCS_SM_CMD_HOST_WALK_PID_MAP,
+ VMCS_SM_CMD_CLEAN_INVALID,
+
VMCS_SM_CMD_LAST /* Do no delete */
};
@@ -163,6 +165,16 @@ struct vmcs_sm_ioctl_cache {
unsigned int size;
};
+struct vmcs_sm_ioctl_clean_invalid {
+ /* user -> kernel */
+ struct {
+ unsigned int cmd;
+ unsigned int handle;
+ unsigned int addr;
+ unsigned int size;
+ } s[8];
+};
+
/* IOCTL numbers */
#define VMCS_SM_IOCTL_MEM_ALLOC\
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_ALLOC,\
@@ -191,6 +203,9 @@ struct vmcs_sm_ioctl_cache {
#define VMCS_SM_IOCTL_MEM_INVALID\
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_INVALID,\
struct vmcs_sm_ioctl_cache)
+#define VMCS_SM_IOCTL_MEM_CLEAN_INVALID\
+ _IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_CLEAN_INVALID,\
+ struct vmcs_sm_ioctl_clean_invalid)
#define VMCS_SM_IOCTL_SIZE_USR_HDL\
_IOR(VMCS_SM_MAGIC_TYPE, VMCS_SM_CMD_SIZE_USR_HANDLE,\
diff --git a/drivers/char/broadcom/vc_sm/vmcs_sm.c b/drivers/char/broadcom/vc_sm/vmcs_sm.c
index da1c52359a0e..39a897151b96 100644
--- a/drivers/char/broadcom/vc_sm/vmcs_sm.c
+++ b/drivers/char/broadcom/vc_sm/vmcs_sm.c
@@ -2732,6 +2732,55 @@ static long vc_sm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
}
break;
+ /* Flush/Invalidate the cache for a given mapping. */
+ case VMCS_SM_CMD_CLEAN_INVALID:
+ {
+ int i;
+ struct vmcs_sm_ioctl_clean_invalid ioparam;
+
+ /* Get parameter data. */
+ if (copy_from_user(&ioparam,
+ (void *)arg, sizeof(ioparam)) != 0) {
+ pr_err("[%s]: failed to copy-from-user for cmd %x\n",
+ __func__, cmdnr);
+ ret = -EFAULT;
+ goto out;
+ }
+ for (i=0; i<sizeof ioparam.s/sizeof *ioparam.s; i++) {
+ switch (ioparam.s[i].cmd) {
+ default: case 0: break; /* NOOP */
+ case 1: /* L1/L2 invalidate virtual range */
+ case 2: /* L1/L2 clean physical range */
+ case 3: /* L1/L2 clean+invalidate all */
+ {
+ /* Locate resource from GUID.
+ */
+ resource =
+ vmcs_sm_acquire_resource(file_data, ioparam.s[i].handle);
+
+ if ((resource != NULL) && resource->res_cached) {
+ unsigned long base = ioparam.s[i].addr & ~(PAGE_SIZE-1);
+ unsigned long end = (ioparam.s[i].addr + ioparam.s[i].size + PAGE_SIZE-1) & ~(PAGE_SIZE-1);
+ resource->res_stats[ioparam.s[i].cmd == 1 ? INVALID:FLUSH]++;
+
+ /* L1/L2 cache flush */
+ down_read(&current->mm->mmap_sem);
+ vcsm_vma_cache_clean_page_range(base, end);
+ up_read(&current->mm->mmap_sem);
+ } else if (resource == NULL) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (resource)
+ vmcs_sm_release_resource(resource, 0);
+ }
+ break;
+ }
+ }
+ }
+ break;
+
default:
{
ret = -EINVAL;