I try to run a program which use the following hidden from me code: It call function to reserve some mem area using the following:
func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer { // On 64-bit, people with ulimit -v set complain if we reserve too // much address space. Instead, assume that the reservation is okay // if we can reserve at least 64K and check the assumption in SysMap. // Only user-mode Linux (UML) rejects these requests. if sys.PtrSize == 8 && uint64(n) > 1<<32 { p, err := mmap_fixed(v, 64<<10, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, mmapFD, 0) if p != v || err != 0 { if err == 0 { munmap(p, 64<<10) } return nil } munmap(p, 64<<10) *reserved = false return v } In Man page related to mmap I found that this combination of flags ignore FD: MAP_PRIVATE Create a private copy-on-write mapping. Updates to the mapping are not visible to other processes mapping the same file, and are not carried through to the underlying file. It is unspecified whether changes made to the file after the mmap() call are visible in the mapped region.
MAP_ANONYMOUS The mapping is not backed by any file; its contents are initialized to zero. The fd argument is ignored; however, some implementations require fd to be -1 if MAP_ANONYMOUS (or MAP_ANON) is specified, and portable applications should ensure this. The offset argument should be zero. The use of MAP_ANONYMOUS in conjunction with MAP_SHARED is supported on Linux only since kernel 2.4.
The code in Genode mmap wrapper try to find anyway the mapping for fd descriptor (-1 in my case) and fail because of libc_fd_to_fd(libc_fd, "mmap");:
__SYS_(void *, mmap, (void *addr, ::size_t length, int prot, int flags, int libc_fd, ::off_t offset), {
/* handle requests for anonymous memory */ if (!addr && libc_fd == -1) { bool const executable = prot & PROT_EXEC; void *start = Libc::mem_alloc(executable)->alloc(length, PAGE_SHIFT); if (!start) { errno = ENOMEM; return MAP_FAILED; } mmap_registry()->insert(start, length, 0); return start; }
/* lookup plugin responsible for file descriptor */ File_descriptor *fd = libc_fd_to_fd(libc_fd, "mmap"); if (!fd || !fd->plugin || !fd->plugin->supports_mmap()) { Genode::warning("mmap not supported for file descriptor ", libc_fd); errno = EBADF; return MAP_FAILED; }
void *start = fd->plugin->mmap(addr, length, prot, flags, fd, offset); mmap_registry()->insert(start, length, fd->plugin); return start; })
I want to add that addr below is non-0, like 0xc000000000 - for Linux and for my test compiled on Genode. So, Anon mapping does not require address to be 0, and as I understand code in file_operations.cchttp://file_operations.cc below should be fixed using MAP_ANONYMOUS flag? Or you think that this is correct check for addr==0 and I need to fix something else?
Отправлено с iPhone
1 сент. 2019 г., в 3:53, Alexander Tormasov via users <users@lists.genode.orgmailto:users@lists.genode.org> написал(а):
I try to run a program which use the following hidden from me code: It call function to reserve some mem area using the following:
func sysReserve(v unsafe.Pointer, n uintptr, reserved *bool) unsafe.Pointer { // On 64-bit, people with ulimit -v set complain if we reserve too // much address space. Instead, assume that the reservation is okay // if we can reserve at least 64K and check the assumption in SysMap. // Only user-mode Linux (UML) rejects these requests. if sys.PtrSize == 8 && uint64(n) > 1<<32 { p, err := mmap_fixed(v, 64<<10, _PROT_NONE, _MAP_ANON|_MAP_PRIVATE, mmapFD, 0) if p != v || err != 0 { if err == 0 { munmap(p, 64<<10) } return nil } munmap(p, 64<<10) *reserved = false return v } In Man page related to mmap I found that this combination of flags ignore FD: MAP_PRIVATE Create a private copy-on-write mapping. Updates to the mapping are not visible to other processes mapping the same file, and are not carried through to the underlying file. It is unspecified whether changes made to the file after the mmap() call are visible in the mapped region.
MAP_ANONYMOUS The mapping is not backed by any file; its contents are initialized to zero. The fd argument is ignored; however, some implementations require fd to be -1 if MAP_ANONYMOUS (or MAP_ANON) is specified, and portable applications should ensure this. The offset argument should be zero. The use of MAP_ANONYMOUS in conjunction with MAP_SHARED is supported on Linux only since kernel 2.4.
The code in Genode mmap wrapper try to find anyway the mapping for fd descriptor (-1 in my case) and fail because of libc_fd_to_fd(libc_fd, "mmap");:
__SYS_(void *, mmap, (void *addr, ::size_t length, int prot, int flags, int libc_fd, ::off_t offset), {
/* handle requests for anonymous memory */ if (!addr && libc_fd == -1) { bool const executable = prot & PROT_EXEC; void *start = Libc::mem_alloc(executable)->alloc(length, PAGE_SHIFT); if (!start) { errno = ENOMEM; return MAP_FAILED; } mmap_registry()->insert(start, length, 0); return start; }
/* lookup plugin responsible for file descriptor */ File_descriptor *fd = libc_fd_to_fd(libc_fd, "mmap"); if (!fd || !fd->plugin || !fd->plugin->supports_mmap()) { Genode::warning("mmap not supported for file descriptor ", libc_fd); errno = EBADF; return MAP_FAILED; }
void *start = fd->plugin->mmap(addr, length, prot, flags, fd, offset); mmap_registry()->insert(start, length, fd->plugin); return start; })
_______________________________________________ Genode users mailing list users@lists.genode.orgmailto:users@lists.genode.org https://lists.genode.org/listinfo/users
Hello Alexander,
On 01.09.19 10:45, Alexander Tormasov via users wrote:
I want to add that addr below is non-0, like 0xc000000000 - for Linux and for my test compiled on Genode.
as you just noticed, Genode's mmap support is rudimentary at best. We took it only as far as needed to accommodate a few common use cases. There is no plan to support the full feature set of Linux. I.e., mmap'ed files as mechanism for shared memory would hardly be feasible. As far as the allocation of anonymous memory via mmap goes, we did not yet encounter your use case where a virtual address is specified. Hence, the implementation does not support it.
I just had a glimpse at the 'Libc::Mem_alloc' code in the libc. It is not impossible but also not straight-forward to extend its interface with an 'alloc_at' method. Do you see a way around it by adjusting the 3rd-party code to not depend on a specific virtual address?
Cheers Norman
Hi! Thank you for clarification.
I just had a glimpse at the 'Libc::Mem_alloc' code in the libc. It is not impossible but also not straight-forward to extend its interface with an 'alloc_at' method. Do you see a way around it by adjusting the 3rd-party code to not depend on a specific virtual address?
Go runtime try to use memory in some standard way - they just reserve (not commit) big address ranges of memory, Then try to map (commit) it by chunks and use for heap and other purposes.
In theory, in the comments Go runtime developers mention that some 64bit systems can’t implement reservation and make just plain allocation. So, I try to force this approach by reserving single big (544mb) memory range using Libc::alloc(). And fail in genode (hang in requesting response from parent for memory extension) - see my other messages to the list today. Probably I can continue moving in this direction - it seems for me like heavy-weight approach.
Idea to be able to alloc just range of memory and reserve it seems more promising. I use similar approach in Windows when I can allocate some virtual memory (without physical ones) and control page faults inside the range by committing faulted pages in exception handler (e.g. making transparent compression on the fly).