Handle hugetlbfs file mapping
Hugetlbfs file mappings are handled differently than regular files: - pager_req_create will tell us the file is in a hugetlbfs - allocate memory upfront, we need to fail if not enough memory - the memory needs to be given again if another process maps the same file This implementation still has some hacks, in particular, the memory needs to be freed when all mappings are done and the file has been deleted/closed by all processes. We cannot know when the file is closed/unlinked easily, so clean up memory when all processes have exited. To test, install libhugetlbfs and link a program with the additional LDFLAGS += -B /usr/share/libhugetlbfs -Wl,--hugetlbfs-align Then run with HUGETLB_ELFMAP=RW set, you can check this works with HUGETLB_DEBUG=1 HUGETLB_VERBOSE=2 Change-Id: I327920ff06efd82e91b319b27319f41912169af1
This commit is contained in:
committed by
Masamichi Takagi
parent
3e3ccf377c
commit
39f9d7fdff
@@ -1614,7 +1614,7 @@ do_mmap(const intptr_t addr0, const size_t len0, const int prot,
|
||||
int p2align;
|
||||
void *p = NULL;
|
||||
int vrflags;
|
||||
intptr_t phys;
|
||||
uintptr_t phys;
|
||||
struct memobj *memobj = NULL;
|
||||
int maxprot;
|
||||
int denied;
|
||||
@@ -1688,7 +1688,7 @@ do_mmap(const intptr_t addr0, const size_t len0, const int prot,
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if (flags & MAP_ANONYMOUS) {
|
||||
/* Obtain mapping address */
|
||||
error = search_free_space(len, PAGE_SHIFT + p2align, &addr);
|
||||
if (error) {
|
||||
@@ -1722,7 +1722,7 @@ do_mmap(const intptr_t addr0, const size_t len0, const int prot,
|
||||
populated_mapping = 0;
|
||||
}
|
||||
|
||||
if (!(prot & PROT_WRITE)) {
|
||||
if ((flags & MAP_ANONYMOUS) && !(prot & PROT_WRITE)) {
|
||||
error = set_host_vma(addr, len, PROT_READ | PROT_EXEC, 1/* holding memory_range_lock */);
|
||||
if (error) {
|
||||
kprintf("do_mmap:set_host_vma failed. %d\n", error);
|
||||
@@ -1774,15 +1774,56 @@ do_mmap(const intptr_t addr0, const size_t len0, const int prot,
|
||||
#ifdef PROFILE_ENABLE
|
||||
profile_event_add(PROFILE_mmap_device_file, len);
|
||||
#endif // PROFILE_ENABLE
|
||||
dkprintf("%s: device fd: %d off: %lu mapping at %p - %p\n",
|
||||
__FUNCTION__, fd, off, addr, addr + len);
|
||||
}
|
||||
}
|
||||
if (error) {
|
||||
kprintf("%s: error: file mapping failed, fd: %d, error: %d\n",
|
||||
__FUNCTION__, error);
|
||||
__func__, fd, error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* hugetlbfs files are pre-created in fileobj_create, but
|
||||
* need extra processing
|
||||
*/
|
||||
if (memobj && (memobj->flags & MF_HUGETLBFS)) {
|
||||
error = hugefileobj_create(memobj, len, off, &pgshift,
|
||||
addr0);
|
||||
if (error) {
|
||||
memobj->ops->free(memobj);
|
||||
kprintf("%s: error creating hugetlbfs memobj, fd: %d, error: %d\n",
|
||||
__func__, fd, error);
|
||||
goto out;
|
||||
}
|
||||
p2align = pgshift - PAGE_SHIFT;
|
||||
}
|
||||
|
||||
/* Obtain mapping address - delayed to use proper p2align */
|
||||
if (!(flags & MAP_FIXED))
|
||||
error = search_free_space(len, PAGE_SHIFT + p2align,
|
||||
&addr);
|
||||
if (error) {
|
||||
ekprintf("do_mmap:search_free_space(%lx,%lx,%d) failed. %d\n",
|
||||
len, region->map_end, p2align, error);
|
||||
goto out;
|
||||
}
|
||||
if (!(prot & PROT_WRITE)) {
|
||||
error = set_host_vma(addr, len, PROT_READ | PROT_EXEC,
|
||||
1/* holding memory_range_lock */);
|
||||
if (error) {
|
||||
kprintf("do_mmap:set_host_vma failed. %d\n",
|
||||
error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ro_vma_mapped = 1;
|
||||
}
|
||||
if (memobj->flags & MF_HUGETLBFS) {
|
||||
dkprintf("Created hugefileobj %p (%d:%x %llx-%llx, fd %d, pgshift %d)\n",
|
||||
memobj, len, off, addr, addr+len, fd, pgshift);
|
||||
} else if (memobj->flags & MF_DEV_FILE) {
|
||||
dkprintf("%s: device fd: %d off: %lu mapping at %p - %p\n",
|
||||
__func__, fd, off, addr, addr + len);
|
||||
}
|
||||
}
|
||||
/* Prepopulated ANONYMOUS mapping */
|
||||
else if (!(vrflags & VR_DEMAND_PAGING)
|
||||
|
||||
Reference in New Issue
Block a user