mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-06 10:00:17 +00:00
vcsm: Add ioctl for custom cache flushing
This commit is contained in:
@@ -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,\
|
||||
|
||||
@@ -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(¤t->mm->mmap_sem);
|
||||
vcsm_vma_cache_clean_page_range(base, end);
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
} else if (resource == NULL) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (resource)
|
||||
vmcs_sm_release_resource(resource, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
ret = -EINVAL;
|
||||
|
||||
Reference in New Issue
Block a user