From 9e88c40e4090a7f5291e9d062a7d250cf95e66d0 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Wed, 20 Mar 2013 18:45:10 +0000 Subject: [PATCH] VM: 64-bit mmap() Some (backwards-compatible) changes in mmap() call message fields that allow for a 64-bit offset. minix_mmap() takes an off_t and minix_mmap64() takes a u64_t. Some mmap() work in VM goes into a separate function, using the new fields, so that that can be re-used when files are to be mapped (future commit). Change-Id: Ifb77a90b593dd3c33cf81b396068e4da1ec5fb1c --- include/minix/com.h | 3 +- lib/libc/sys-minix/mmap.c | 10 +++-- servers/vm/mmap.c | 95 ++++++++++++++++++++++++--------------- sys/sys/mman.h | 3 +- 4 files changed, 71 insertions(+), 40 deletions(-) diff --git a/include/minix/com.h b/include/minix/com.h index c43c412dd..1daa0409a 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -942,8 +942,9 @@ # define VMM_PROT m5_s1 # define VMM_FLAGS m5_s2 # define VMM_FD m5_i1 -# define VMM_OFFSET m5_i2 +# define VMM_OFFSET_LO m5_i2 # define VMM_FORWHOM m5_l3 +# define VMM_OFFSET_HI m5_l3 # define VMM_RETADDR m5_l1 /* result */ #define VM_UMAP (VM_RQ_BASE+11) # define VMU_SEG m1_i1 diff --git a/lib/libc/sys-minix/mmap.c b/lib/libc/sys-minix/mmap.c index 19e4d8170..4a3de773e 100644 --- a/lib/libc/sys-minix/mmap.c +++ b/lib/libc/sys-minix/mmap.c @@ -2,6 +2,8 @@ #include #include "namespace.h" #include +#include +#include /* INCLUDES HERE */ @@ -21,7 +23,7 @@ __weak_alias(minix_munmap, _minix_munmap) #include void *minix_mmap_for(endpoint_t forwhom, - void *addr, size_t len, int prot, int flags, int fd, off_t offset) + void *addr, size_t len, int prot, int flags, int fd, u64_t offset) { message m; int r; @@ -31,11 +33,13 @@ void *minix_mmap_for(endpoint_t forwhom, m.VMM_PROT = prot; m.VMM_FLAGS = flags; m.VMM_FD = fd; - m.VMM_OFFSET = offset; - m.VMM_FORWHOM = forwhom; + m.VMM_OFFSET_LO = ex64lo(offset); if(forwhom != SELF) { m.VMM_FLAGS |= MAP_THIRDPARTY; + m.VMM_FORWHOM = forwhom; + } else { + m.VMM_OFFSET_HI = ex64hi(offset); } r = _syscall(VM_PROC_NR, VM_MMAP, &m); diff --git a/servers/vm/mmap.c b/servers/vm/mmap.c index 8a9bf22e6..1cdc677a0 100644 --- a/servers/vm/mmap.c +++ b/servers/vm/mmap.c @@ -32,6 +32,58 @@ #include "util.h" #include "region.h" + +static struct vir_region *mmap_region(struct vmproc *vmp, vir_bytes addr, + u32_t vmm_flags, size_t len, u32_t vrflags, + mem_type_t *mt, int execpriv) +{ + u32_t mfflags = 0; + struct vir_region *vr = NULL; + + if(vmm_flags & MAP_LOWER16M) vrflags |= VR_LOWER16MB; + if(vmm_flags & MAP_LOWER1M) vrflags |= VR_LOWER1MB; + if(vmm_flags & MAP_ALIGN64K) vrflags |= VR_PHYS64K; + if(vmm_flags & MAP_PREALLOC) mfflags |= MF_PREALLOC; + if(vmm_flags & MAP_UNINITIALIZED) { + if(!execpriv) return NULL; + vrflags |= VR_UNINITIALIZED; + } + + if(len <= 0) { + return NULL; + } + + if(len % VM_PAGE_SIZE) + len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE); + +#if 0 + /* MAP_FIXED is restored in a later commit */ + if (addr && (vmm_flags & MAP_FIXED)) { + int r = map_unmap_range(vmp, addr, len); + if(r != OK) { + printf("mmap_region: map_unmap_range failed (%d)\n", r); + return NULL; + } + } +#endif + + if (addr || (vmm_flags & MAP_FIXED)) { + /* An address is given, first try at that address. */ + vr = map_page_region(vmp, addr, 0, len, + vrflags, mfflags, mt); + if(!vr && (vmm_flags & MAP_FIXED)) + return NULL; + } + + if (!vr) { + /* No address given or address already in use. */ + vr = map_page_region(vmp, VM_PAGE_SIZE, VM_DATATOP, len, + vrflags, mfflags, mt); + } + + return vr; +} + /*===========================================================================* * do_mmap * *===========================================================================*/ @@ -39,10 +91,10 @@ int do_mmap(message *m) { int r, n; struct vmproc *vmp; - int mfflags = 0; - vir_bytes addr; + vir_bytes addr = m->VMM_ADDR; struct vir_region *vr = NULL; int execpriv = 0; + size_t len = (vir_bytes) m->VMM_LEN; /* RS and VFS can do slightly more special mmap() things */ if(m->m_source == VFS_PROC_NR || m->m_source == RS_PROC_NR) @@ -63,11 +115,11 @@ int do_mmap(message *m) vmp = &vmproc[n]; if(m->VMM_FD == -1 || (m->VMM_FLAGS & MAP_ANON)) { - mem_type_t *mt; - u32_t vrflags = VR_ANON | VR_WRITABLE; - size_t len = (vir_bytes) m->VMM_LEN; + /* actual memory in some form */ + mem_type_t *mt = NULL; if(m->VMM_FD != -1 || len <= 0) { + printf("VM: mmap: fd %d, len 0x%x\n", m->VMM_FD, len); return EINVAL; } @@ -76,48 +128,21 @@ int do_mmap(message *m) return EINVAL; } - if(m->VMM_FLAGS & MAP_PREALLOC) mfflags |= MF_PREALLOC; - if(m->VMM_FLAGS & MAP_LOWER16M) vrflags |= VR_LOWER16MB; - if(m->VMM_FLAGS & MAP_LOWER1M) vrflags |= VR_LOWER1MB; - if(m->VMM_FLAGS & MAP_ALIGN64K) vrflags |= VR_PHYS64K; - if(m->VMM_FLAGS & MAP_UNINITIALIZED) { - if(!execpriv) return EPERM; - vrflags |= VR_UNINITIALIZED; - } if(m->VMM_FLAGS & MAP_CONTIG) { - vrflags |= VR_CONTIG; mt = &mem_type_anon_contig; } else mt = &mem_type_anon; - if(len % VM_PAGE_SIZE) - len += VM_PAGE_SIZE - (len % VM_PAGE_SIZE); - - vr = NULL; - if (m->VMM_ADDR || (m->VMM_FLAGS & MAP_FIXED)) { - /* An address is given, first try at that address. */ - addr = m->VMM_ADDR; - vr = map_page_region(vmp, addr, 0, len, - vrflags, mfflags, mt); - if(!vr && (m->VMM_FLAGS & MAP_FIXED)) - return ENOMEM; - } - if (!vr) { - /* No address given or address already in use. */ - vr = map_page_region(vmp, 0, VM_DATATOP, len, - vrflags, mfflags, mt); - } - if (!vr) { + if(!(vr = mmap_region(vmp, addr, m->VMM_FLAGS, len, + VR_WRITABLE | VR_ANON, mt, execpriv))) { return ENOMEM; } } else { - return ENOSYS; + return ENXIO; } /* Return mapping, as seen from process. */ - assert(vr); m->VMM_RETADDR = vr->vaddr; - return OK; } diff --git a/sys/sys/mman.h b/sys/sys/mman.h index c4265f563..2c37e14c4 100644 --- a/sys/sys/mman.h +++ b/sys/sys/mman.h @@ -106,7 +106,8 @@ void * mmap(void *, size_t, int, int, int, off_t); int munmap(void *, size_t); #else void * minix_mmap(void *, size_t, int, int, int, off_t); -void * minix_mmap_for(endpoint_t, void *, size_t, int, int, int, off_t); +void * minix_mmap64(void *, size_t, int, int, int, u64_t); +void * minix_mmap_for(endpoint_t, void *, size_t, int, int, int, u64_t); int minix_munmap(void *, size_t); void * vm_remap(endpoint_t d, endpoint_t s, void *da, void *sa, size_t si); void * vm_remap_ro(endpoint_t d, endpoint_t s, void *da, void *sa, size_t si);