device file mappings: communicate map flags and fault missing translations
This commit is contained in:
@ -2261,6 +2261,7 @@ int read_process_vm(struct process_vm *vm, void *kdst, const void *usrc, size_t
|
||||
if ((ustart < vm->region.user_start)
|
||||
|| (vm->region.user_end <= ustart)
|
||||
|| ((vm->region.user_end - ustart) < siz)) {
|
||||
kprintf("%s: error: out of user range\n", __FUNCTION__);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
@ -2268,6 +2269,7 @@ int read_process_vm(struct process_vm *vm, void *kdst, const void *usrc, size_t
|
||||
for (addr = ustart & PAGE_MASK; addr < uend; addr += PAGE_SIZE) {
|
||||
error = page_fault_process_vm(vm, (void *)addr, reason);
|
||||
if (error) {
|
||||
kprintf("%s: error: PF for %p failed\n", __FUNCTION__, addr);
|
||||
return error;
|
||||
}
|
||||
}
|
||||
@ -2283,6 +2285,7 @@ int read_process_vm(struct process_vm *vm, void *kdst, const void *usrc, size_t
|
||||
|
||||
error = ihk_mc_pt_virt_to_phys(vm->address_space->page_table, from, &pa);
|
||||
if (error) {
|
||||
kprintf("%s: error: resolving physical address or %p\n", __FUNCTION__, from);
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
@ -899,7 +899,7 @@ static int pager_req_create(ihk_os_t os, int fd, uintptr_t result_pa)
|
||||
|
||||
error = vfs_fstat(fd, &st);
|
||||
if (error) {
|
||||
dprintk("pager_req_create(%d,%lx):vfs_stat failed. %d\n", fd, (long)result_pa, error);
|
||||
printk("pager_req_create(%d,%lx):vfs_stat failed. %d\n", fd, (long)result_pa, error);
|
||||
goto out;
|
||||
}
|
||||
if (S_ISCHR(st.mode) && (MAJOR(st.rdev) == 1)) {
|
||||
@ -914,7 +914,7 @@ static int pager_req_create(ihk_os_t os, int fd, uintptr_t result_pa)
|
||||
file = fget(fd);
|
||||
if (!file) {
|
||||
error = -EBADF;
|
||||
dprintk("pager_req_create(%d,%lx):file not found. %d\n", fd, (long)result_pa, error);
|
||||
printk("pager_req_create(%d,%lx):file not found. %d\n", fd, (long)result_pa, error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -937,7 +937,7 @@ static int pager_req_create(ihk_os_t os, int fd, uintptr_t result_pa)
|
||||
}
|
||||
if (!(maxprot & PROT_READ)) {
|
||||
error = -EACCES;
|
||||
dprintk("pager_req_create(%d,%lx):cannot read file. %d\n", fd, (long)result_pa, error);
|
||||
printk("pager_req_create(%d,%lx):cannot read file. %d\n", fd, (long)result_pa, error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@ -1209,7 +1209,7 @@ struct pager_map_result {
|
||||
};
|
||||
|
||||
static int pager_req_map(ihk_os_t os, int fd, size_t len, off_t off,
|
||||
uintptr_t result_rpa, int prot)
|
||||
uintptr_t result_rpa, int prot_and_flags)
|
||||
{
|
||||
const ihk_device_t dev = ihk_os_to_dev(os);
|
||||
const off_t pgoff = off / PAGE_SIZE;
|
||||
@ -1237,27 +1237,33 @@ static int pager_req_map(ihk_os_t os, int fd, size_t len, off_t off,
|
||||
}
|
||||
|
||||
maxprot = 0;
|
||||
if (file->f_mode & FMODE_READ) {
|
||||
if ((file->f_mode & FMODE_READ) &&
|
||||
(prot_and_flags ? (prot_and_flags & PROT_READ) : 1)) {
|
||||
maxprot |= PROT_READ;
|
||||
}
|
||||
if ((file->f_mode & FMODE_WRITE) && (prot ? (prot & PROT_WRITE) : 1)) {
|
||||
if ((file->f_mode & FMODE_WRITE) &&
|
||||
(prot_and_flags ? (prot_and_flags & PROT_WRITE) : 1)) {
|
||||
maxprot |= PROT_WRITE;
|
||||
}
|
||||
if (!(file->f_path.mnt->mnt_flags & MNT_NOEXEC)) {
|
||||
if (!(file->f_path.mnt->mnt_flags & MNT_NOEXEC) &&
|
||||
(prot_and_flags ? (prot_and_flags & PROT_EXEC) : 1)) {
|
||||
maxprot |= PROT_EXEC;
|
||||
}
|
||||
|
||||
down_write(¤t->mm->mmap_sem);
|
||||
#define ANY_WHERE 0
|
||||
if (prot_and_flags & MAP_LOCKED) prot_and_flags |= MAP_POPULATE;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
|
||||
va = do_mmap_pgoff(file, ANY_WHERE, len, maxprot, MAP_SHARED, pgoff);
|
||||
va = do_mmap_pgoff(file, ANY_WHERE, len, maxprot,
|
||||
MAP_SHARED | (prot_and_flags & (MAP_POPULATE | MAP_LOCKED)), pgoff);
|
||||
#endif
|
||||
|
||||
up_write(¤t->mm->mmap_sem);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
|
||||
va = vm_mmap(file, ANY_WHERE, len, maxprot, MAP_SHARED, pgoff << PAGE_SHIFT);
|
||||
va = vm_mmap(file, ANY_WHERE, len, maxprot, MAP_SHARED |
|
||||
(prot_and_flags & (MAP_POPULATE | MAP_LOCKED)), pgoff << PAGE_SHIFT);
|
||||
#endif
|
||||
|
||||
if (IS_ERR_VALUE(va)) {
|
||||
@ -1271,8 +1277,8 @@ static int pager_req_map(ihk_os_t os, int fd, size_t len, off_t off,
|
||||
pager->map_len = len;
|
||||
pager->map_off = off;
|
||||
|
||||
dprintk("pager_req_map(%s): 0x%lx - 0x%lx (len: %lu)\n",
|
||||
file->f_dentry->d_name.name, va, va + len, len);
|
||||
dprintk("pager_req_map(%s): 0x%lx - 0x%lx (len: %lu), map_off: %lu\n",
|
||||
file->f_dentry->d_name.name, va, va + len, len, off);
|
||||
|
||||
phys = ihk_device_map_memory(dev, result_rpa, sizeof(*resp));
|
||||
resp = ihk_device_map_virtual(dev, phys, sizeof(*resp), NULL, 0);
|
||||
@ -1309,6 +1315,7 @@ static int pager_req_pfn(ihk_os_t os, uintptr_t handle, off_t off, uintptr_t ppf
|
||||
pte_t *pte;
|
||||
uintptr_t phys;
|
||||
uintptr_t *ppfn;
|
||||
int page_fault_attempted = 0;
|
||||
|
||||
dprintk("pager_req_pfn(%p,%lx,%lx)\n", os, handle, off);
|
||||
|
||||
@ -1324,6 +1331,7 @@ static int pager_req_pfn(ihk_os_t os, uintptr_t handle, off_t off, uintptr_t ppf
|
||||
pfn = PFN_VALID; /* デフォルトは not present */
|
||||
|
||||
down_read(¤t->mm->mmap_sem);
|
||||
retry:
|
||||
pgd = pgd_offset(current->mm, va);
|
||||
if (!pgd_none(*pgd) && !pgd_bad(*pgd) && pgd_present(*pgd)) {
|
||||
pud = pud_offset(pgd, va);
|
||||
@ -1346,6 +1354,33 @@ static int pager_req_pfn(ihk_os_t os, uintptr_t handle, off_t off, uintptr_t ppf
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If not present, try to fault it */
|
||||
if (!(pfn & PFN_PRESENT) && !page_fault_attempted) {
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
struct vm_area_struct *vma;
|
||||
int fault;
|
||||
|
||||
flags |= FAULT_FLAG_USER;
|
||||
|
||||
vma = find_vma(current->mm, va);
|
||||
if (!vma || (va < vma->vm_start)) {
|
||||
printk("%s: couldn't find VMA for va %lx\n", __FUNCTION__, va);
|
||||
error = -EINVAL;
|
||||
goto out_release;
|
||||
}
|
||||
|
||||
fault = handle_mm_fault(current->mm, vma, va, flags);
|
||||
if (fault != 0) {
|
||||
printk("%s: error: faulting %lx at off: %lu\n",
|
||||
__FUNCTION__, va, off);
|
||||
}
|
||||
|
||||
page_fault_attempted = 1;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
out_release:
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
|
||||
phys = ihk_device_map_memory(dev, ppfn_rpa, sizeof(*ppfn));
|
||||
|
||||
@ -79,7 +79,7 @@ static struct memobj *to_memobj(struct devobj *devobj)
|
||||
* devobj
|
||||
*/
|
||||
int devobj_create(int fd, size_t len, off_t off, struct memobj **objp, int *maxprotp,
|
||||
int prot)
|
||||
int prot, int populate_flags)
|
||||
{
|
||||
ihk_mc_user_context_t ctx;
|
||||
struct pager_map_result result; // XXX: assumes contiguous physical
|
||||
@ -116,7 +116,7 @@ int devobj_create(int fd, size_t len, off_t off, struct memobj **objp, int *maxp
|
||||
ihk_mc_syscall_arg2(&ctx) = len;
|
||||
ihk_mc_syscall_arg3(&ctx) = off;
|
||||
ihk_mc_syscall_arg4(&ctx) = virt_to_phys(&result);
|
||||
ihk_mc_syscall_arg5(&ctx) = prot;
|
||||
ihk_mc_syscall_arg5(&ctx) = prot | populate_flags;
|
||||
|
||||
error = syscall_generic_forwarding(__NR_mmap, &ctx);
|
||||
if (error) {
|
||||
@ -206,7 +206,7 @@ static void devobj_release(struct memobj *memobj)
|
||||
|
||||
static int devobj_get_page(struct memobj *memobj, off_t off, int p2align, uintptr_t *physp, unsigned long *flag)
|
||||
{
|
||||
const off_t pgoff = off >> PAGE_SHIFT;
|
||||
const off_t pgoff = off / PAGE_SIZE;
|
||||
struct devobj *obj = to_devobj(memobj);
|
||||
int error;
|
||||
uintptr_t pfn;
|
||||
@ -218,7 +218,7 @@ static int devobj_get_page(struct memobj *memobj, off_t off, int p2align, uintpt
|
||||
|
||||
if ((pgoff < obj->pfn_pgoff) || ((obj->pfn_pgoff + obj->npages) <= pgoff)) {
|
||||
error = -EFBIG;
|
||||
kprintf("devobj_get_page(%p %lx,%lx,%d): out of range. %d\n", memobj, obj->handle, off, p2align, error);
|
||||
kprintf("%s: error: out of range: off: %lu, page off: %lu obj->npages: %d\n", __FUNCTION__, off, pgoff, obj->npages);
|
||||
goto out;
|
||||
}
|
||||
ix = pgoff - obj->pfn_pgoff;
|
||||
|
||||
@ -182,7 +182,7 @@ int fileobj_create(int fd, struct memobj **objp, int *maxprotp)
|
||||
|
||||
error = syscall_generic_forwarding(__NR_mmap, &ctx);
|
||||
if (error) {
|
||||
kprintf("fileobj_create(%d):create failed. %d\n", fd, error);
|
||||
dkprintf("fileobj_create(%d):create failed. %d\n", fd, error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@ -142,6 +142,6 @@ struct shmid_ds;
|
||||
int shmobj_create(struct shmid_ds *ds, struct memobj **objp);
|
||||
int zeroobj_create(struct memobj **objp);
|
||||
int devobj_create(int fd, size_t len, off_t off, struct memobj **objp, int *maxprotp,
|
||||
int prot);
|
||||
int prot, int populate_flags);
|
||||
|
||||
#endif /* HEADER_MEMOBJ_H */
|
||||
|
||||
@ -1641,6 +1641,18 @@ static int do_page_fault_process_vm(struct process_vm *vm, void *fault_addr0, ui
|
||||
"access denied. %d\n",
|
||||
ihk_mc_get_processor_id(), vm,
|
||||
fault_addr0, reason, error);
|
||||
kprintf("%s: reason: %s%s%s%s%s%s%s%s\n", __FUNCTION__,
|
||||
(reason & PF_PROT) ? "PF_PROT " : "",
|
||||
(reason & PF_WRITE) ? "PF_WRITE " : "",
|
||||
(reason & PF_USER) ? "PF_USER " : "",
|
||||
(reason & PF_RSVD) ? "PF_RSVD " : "",
|
||||
(reason & PF_INSTR) ? "PF_INSTR " : "",
|
||||
(reason & PF_PATCH) ? "PF_PATCH " : "",
|
||||
(reason & PF_POPULATE) ? "PF_POPULATE " : "");
|
||||
kprintf("%s: range->flag & (%s%s%s)\n", __FUNCTION__,
|
||||
(range->flag & VR_PROT_READ) ? "VR_PROT_READ " : "",
|
||||
(range->flag & VR_PROT_WRITE) ? "VR_PROT_WRITE " : "",
|
||||
(range->flag & VR_PROT_EXEC) ? "VR_PROT_EXEC " : "");
|
||||
if (((range->flag & VR_PROT_MASK) == VR_PROT_NONE))
|
||||
kprintf("if (((range->flag & VR_PROT_MASK) == VR_PROT_NONE))\n");
|
||||
if (((reason & PF_WRITE) && !(reason & PF_PATCH)))
|
||||
|
||||
@ -1097,7 +1097,7 @@ do_mmap(const intptr_t addr0, const size_t len0, const int prot,
|
||||
}
|
||||
#endif
|
||||
if (error == -ESRCH) {
|
||||
kprintf("do_mmap:hit non VREG\n");
|
||||
dkprintf("do_mmap:hit non VREG\n");
|
||||
/*
|
||||
* XXX: temporary:
|
||||
*
|
||||
@ -1108,10 +1108,17 @@ do_mmap(const intptr_t addr0, const size_t len0, const int prot,
|
||||
vrflags &= ~VR_MEMTYPE_MASK;
|
||||
vrflags |= VR_MEMTYPE_UC;
|
||||
}
|
||||
error = devobj_create(fd, len, off, &memobj, &maxprot, prot);
|
||||
error = devobj_create(fd, len, off, &memobj, &maxprot,
|
||||
prot, (flags & (MAP_POPULATE | MAP_LOCKED)));
|
||||
|
||||
if (!error) {
|
||||
dkprintf("%s: device fd: %d off: %lu mapping at %p - %p\n",
|
||||
__FUNCTION__, fd, off, addr, addr + len);
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
ekprintf("do_mmap:fileobj_create failed. %d\n", error);
|
||||
kprintf("%s: error: file mapping failed, fd: %d, error: %d\n",
|
||||
__FUNCTION__, error);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@ -1181,9 +1188,12 @@ out:
|
||||
if (!error && populated_mapping) {
|
||||
error = populate_process_memory(thread->vm, (void *)addr, len);
|
||||
if (error) {
|
||||
ekprintf("do_mmap:populate_process_memory"
|
||||
"(%p,%p,%lx) failed %d\n",
|
||||
thread->vm, (void *)addr, len, error);
|
||||
ekprintf("%s: error :populate_process_memory"
|
||||
"vm: %p, addr: %p, len: %d (flags: %s%s) failed %d\n", __FUNCTION__,
|
||||
thread->vm, (void *)addr, len,
|
||||
(flags & MAP_POPULATE) ? "MAP_POPULATE " : "",
|
||||
(flags & MAP_LOCKED) ? "MAP_LOCKED ": "",
|
||||
error);
|
||||
/*
|
||||
* In this case,
|
||||
* the mapping established by this call should be unmapped
|
||||
@ -5574,7 +5584,7 @@ SYSCALL_DECLARE(sched_setaffinity)
|
||||
len = MIN2(len, sizeof(k_cpu_set));
|
||||
|
||||
if (copy_from_user(&k_cpu_set, u_cpu_set, len)) {
|
||||
kprintf("%s:%d copy_from_user failed.\n", __FILE__, __LINE__);
|
||||
kprintf("%s: error: copy_from_user failed for %p:%d\n", __FUNCTION__, u_cpu_set, len);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user