diff --git a/drivers/ub/obmm/obmm_core.h b/drivers/ub/obmm/obmm_core.h index 4d844334dbadb5f77eb7b03cab065adb22771d26..ff3e717754efc1b0cd783b1534e09c7275076875 100644 --- a/drivers/ub/obmm/obmm_core.h +++ b/drivers/ub/obmm/obmm_core.h @@ -87,6 +87,7 @@ struct obmm_region { struct cdev cdevice; struct device device; + atomic_t device_released; refcount_t refcnt; diff --git a/drivers/ub/obmm/obmm_export.c b/drivers/ub/obmm/obmm_export.c index e1ec90cf15dd476f8471e3358dab16411930aeb8..237eb1e122f92a173fff41c1f9581a2431f8088f 100644 --- a/drivers/ub/obmm/obmm_export.c +++ b/drivers/ub/obmm/obmm_export.c @@ -25,6 +25,7 @@ #include "obmm_core.h" #include "obmm_cache.h" #include "obmm_export.h" +#include "obmm_shm_dev.h" int export_flags_to_region_flags(unsigned long *region_flags, unsigned long user_flags) { @@ -266,6 +267,7 @@ int set_export_vendor(struct obmm_export_region *e_reg, const void __user *vendo void free_export_region(struct obmm_export_region *e_reg) { + wait_until_dev_released(&e_reg->region); if (e_reg->vendor_len) kfree(e_reg->vendor_info); diff --git a/drivers/ub/obmm/obmm_export_from_pool.c b/drivers/ub/obmm/obmm_export_from_pool.c index dabf5373ea2cd05b78dd0a228da24326b99e4b21..daa4214955da9e615638a48f97829fba4d3dbf8c 100644 --- a/drivers/ub/obmm/obmm_export_from_pool.c +++ b/drivers/ub/obmm/obmm_export_from_pool.c @@ -255,6 +255,8 @@ static struct obmm_export_region *alloc_region_from_cmd(struct obmm_cmd_export * if (e_reg == NULL) return ERR_PTR(-ENOMEM); + atomic_set(&e_reg->region.device_released, 1); + e_reg->region.type = OBMM_EXPORT_REGION; e_reg->region.mem_size = total_size; e_reg->region.mem_cap = OBMM_MEM_ALLOW_CACHEABLE_MMAP | OBMM_MEM_ALLOW_NONCACHEABLE_MMAP; diff --git a/drivers/ub/obmm/obmm_export_from_user.c b/drivers/ub/obmm/obmm_export_from_user.c index bd0663bb197f492b83b6811472c6ad851339bbee..f136d3398753a3eb97e36a003c18f592b65e53d0 100644 --- a/drivers/ub/obmm/obmm_export_from_user.c +++ b/drivers/ub/obmm/obmm_export_from_user.c @@ -255,6 +255,10 @@ static int obmm_cmd_export_pid_allowed(struct obmm_cmd_export_pid *cmd) pr_err("ALLOW_MMAP flag is not allowed in export_user_addr.\n"); return -EINVAL; } + if (cmd->flags & OBMM_EXPORT_FLAG_FAST) { + pr_err("FAST flag is not allowed in export_user_addr.\n"); + return -EINVAL; + } if (cmd->length == 0) { pr_err("export sizeof 0 memory is not allowed.\n"); @@ -279,6 +283,8 @@ alloc_export_region_from_obmm_cmd_export_pid(const struct obmm_cmd_export_pid *e if (e_reg == NULL) return ERR_PTR(-ENOMEM); + atomic_set(&e_reg->region.device_released, 1); + e_reg->mem_desc_pid.pid = export_pid->pid; e_reg->mem_desc_pid.user_va = export_pid->va; e_reg->region.mem_size = export_pid->length; diff --git a/drivers/ub/obmm/obmm_import.c b/drivers/ub/obmm/obmm_import.c index 18f59efa90c6014a1b4c6b0f219b8718a14c61d9..4a56a86f68f273ff343d0a2d409982668f18393c 100644 --- a/drivers/ub/obmm/obmm_import.c +++ b/drivers/ub/obmm/obmm_import.c @@ -16,6 +16,7 @@ #include "obmm_preimport.h" #include "obmm_resource.h" #include "obmm_addr_check.h" +#include "obmm_shm_dev.h" static void set_import_region_datapath(const struct obmm_import_region *i_reg, struct obmm_datapath *datapath) @@ -415,6 +416,8 @@ int obmm_import(struct obmm_cmd_import *cmd_import) if (i_reg == NULL) return -ENOMEM; + atomic_set(&i_reg->region.device_released, 1); + /* arguments to region (logs produced by callee) */ retval = init_import_region_from_cmd(cmd_import, i_reg); if (retval) @@ -455,6 +458,7 @@ int obmm_import(struct obmm_cmd_import *cmd_import) out_region_uninit: uninit_obmm_region(&i_reg->region); out_free_ireg: + wait_until_dev_released(&i_reg->region); kfree(i_reg); return retval; } @@ -493,6 +497,7 @@ int obmm_unimport(const struct obmm_cmd_unimport *cmd_unimport) deregister_obmm_region(reg); uninit_obmm_region(reg); + wait_until_dev_released(&i_reg->region); kfree(i_reg); pr_info("%s: mem_id=%llu completed.\n", __func__, cmd_unimport->mem_id); diff --git a/drivers/ub/obmm/obmm_shm_dev.c b/drivers/ub/obmm/obmm_shm_dev.c index 0272287fea640ca23b16ee1302b03240513b3ffb..0814c37d12b46ca600fb95f5a96868548003d44d 100644 --- a/drivers/ub/obmm/obmm_shm_dev.c +++ b/drivers/ub/obmm/obmm_shm_dev.c @@ -310,7 +310,7 @@ static int obmm_shm_fops_mmap(struct file *file, struct vm_area_struct *vma) unsigned long size, offset; uint8_t mem_state; enum obmm_mmap_mode old_mmap_mode; - enum obmm_mmap_granu mmap_granu; + enum obmm_mmap_granu mmap_granu, init_mmap_granu; int ret; bool cacheable, o_sync; @@ -331,21 +331,23 @@ static int obmm_shm_fops_mmap(struct file *file, struct vm_area_struct *vma) if (offset & OBMM_MMAP_FLAG_HUGETLB_PMD) { pr_debug("trying hugepage mmap\n"); - mmap_granu = OBMM_MMAP_GRANU_PMD; offset &= ~OBMM_MMAP_FLAG_HUGETLB_PMD; if (vma->vm_start % PMD_SIZE || vma->vm_end % PMD_SIZE) { pr_err("error running huge mmap for not pmd-aligned vma: %#lx-%#lx\n", vma->vm_start, vma->vm_end); return -EINVAL; } + mmap_granu = OBMM_MMAP_GRANU_PMD; } else { mmap_granu = OBMM_MMAP_GRANU_PAGE; } + init_mmap_granu = reg->mmap_granu; if (reg->mmap_granu == OBMM_MMAP_GRANU_NONE) { reg->mmap_granu = mmap_granu; } else if (reg->mmap_granu != mmap_granu) { pr_err("map with PAGE_SIZE and PMD_SIZE granu should not be mixed on the same region\n"); - return -EINVAL; + ret = -EPERM; + goto err_reset_mmap_granu; } vma->vm_pgoff = offset >> PAGE_SHIFT; @@ -353,7 +355,8 @@ static int obmm_shm_fops_mmap(struct file *file, struct vm_area_struct *vma) if (offset >= reg->mem_size || size > reg->mem_size - offset) { pr_err("mmap region %d: offset:%#lx, size:%#lx over region size: %#llx", reg->regionid, offset, size, reg->mem_size); - return -EINVAL; + ret = -EINVAL; + goto err_reset_mmap_granu; } /* @@ -404,6 +407,11 @@ static int obmm_shm_fops_mmap(struct file *file, struct vm_area_struct *vma) ret = init_ownership_info(reg); if (ret) goto err_release_local_state_info; + /* + * after ownership_info initialized, mmap_granu should not be + * reset to OBMM_MMAP_GRANU_NONE. + */ + init_mmap_granu = reg->mmap_granu; ret = check_mmap_allowed(reg, vma, mem_state); if (ret) goto err_release_local_state_info; @@ -454,6 +462,8 @@ static int obmm_shm_fops_mmap(struct file *file, struct vm_area_struct *vma) reg->mmap_mode = OBMM_MMAP_INIT; err_mutex_unlock: mutex_unlock(®->state_mutex); +err_reset_mmap_granu: + reg->mmap_granu = init_mmap_granu; return ret; } @@ -881,9 +891,18 @@ const struct file_operations obmm_shm_fops = { .owner = THIS_MODULE, static void obmm_shm_dev_release(struct device *dev) { + struct obmm_region *reg = container_of(dev, struct obmm_region, device); + + atomic_set(®->device_released, 1); module_put(THIS_MODULE); } +void wait_until_dev_released(struct obmm_region *reg) +{ + while (atomic_read(®->device_released) == 0) + cpu_relax(); +} + int obmm_shm_dev_add(struct obmm_region *reg) { int ret; @@ -918,6 +937,8 @@ int obmm_shm_dev_add(struct obmm_region *reg) goto err_put_dev; } + atomic_set(®->device_released, 0); + return 0; /* NOTE: If the device is properly initialized, the refcount of module diff --git a/drivers/ub/obmm/obmm_shm_dev.h b/drivers/ub/obmm/obmm_shm_dev.h index bfced747a2aafd83093a7a38f1ec599e54616d5e..e0bf3553a3ce61f30cb3a829a2ad58439c2be21a 100644 --- a/drivers/ub/obmm/obmm_shm_dev.h +++ b/drivers/ub/obmm/obmm_shm_dev.h @@ -12,5 +12,7 @@ int obmm_shm_dev_init(void); void obmm_shm_dev_exit(void); int obmm_shm_dev_add(struct obmm_region *reg); void obmm_shm_dev_del(struct obmm_region *reg); +void wait_until_dev_released(struct obmm_region *reg); + #endif