From d3e83a9c82b4a57c24061828db6a309692f7f2d4 Mon Sep 17 00:00:00 2001 From: Florin Coras Date: Tue, 16 Jan 2018 02:40:18 -0800 Subject: [PATCH] ssvm: reuse clib mem infra for memfd segments Change-Id: I67648dbed3c7ed291b3e1ce617d83a776d3623bb Signed-off-by: Florin Coras --- src/svm/ssvm.c | 108 ++++++++++++++++++++++----------------------- src/svm/ssvm.h | 16 +------ src/svm/svm_fifo_segment.h | 2 +- src/vppinfra/linux/mem.c | 57 +++++++++++++++++++++--- src/vppinfra/mem.h | 15 ++++++- 5 files changed, 119 insertions(+), 79 deletions(-) diff --git a/src/svm/ssvm.c b/src/svm/ssvm.c index 9b935e4a3bd..36abc208636 100644 --- a/src/svm/ssvm.c +++ b/src/svm/ssvm.c @@ -205,62 +205,38 @@ ssvm_delete (ssvm_private_t * ssvm) int ssvm_master_init_memfd (ssvm_private_t * memfd, u32 master_index) { - int flags; + uword page_size, flags = MHEAP_FLAG_DISABLE_VM | MHEAP_FLAG_THREAD_SAFE; ssvm_shared_header_t *sh; - u64 ticks = clib_cpu_time_now (); - u64 randomize_baseva; void *oldheap; + clib_mem_vm_alloc_t alloc = { 0 }; + clib_error_t *err; if (memfd->ssvm_size == 0) return SSVM_API_ERROR_NO_SIZE; ASSERT (vec_c_string_is_terminated (memfd->name)); - memfd->name = format (0, "memfd svm region %d", master_index); + memfd->name = format (0, "memfd svm region %d%c", master_index, 0); - memfd->fd = memfd_create ((char *) memfd->name, MFD_ALLOW_SEALING); - if (memfd->fd < 0) + alloc.name = (char *) memfd->name; + alloc.size = memfd->ssvm_size; + alloc.flags = CLIB_MEM_VM_F_SHARED; + if ((err = clib_mem_vm_ext_alloc (&alloc))) { - clib_unix_warning ("create segment '%s'", memfd->name); + clib_error_report (err); return SSVM_API_ERROR_CREATE_FAILURE; } - if ((ftruncate (memfd->fd, memfd->ssvm_size)) == -1) - { - clib_unix_warning ("set memfd size"); - return SSVM_API_ERROR_SET_SIZE; - } - - if ((fcntl (memfd->fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1) - clib_unix_warning ("fcntl (F_ADD_SEALS, F_SEAL_SHRINK)"); - - flags = MAP_SHARED; - if (memfd->requested_va) - flags |= MAP_FIXED; - - randomize_baseva = (ticks & 15) * MMAP_PAGESIZE; - - if (memfd->requested_va) - memfd->requested_va += randomize_baseva; - - sh = memfd->sh = - (ssvm_shared_header_t *) mmap ((void *) memfd->requested_va, - memfd->ssvm_size, PROT_READ | PROT_WRITE, - flags, memfd->fd, 0); - - if (memfd->sh == MAP_FAILED) - { - clib_unix_warning ("mmap"); - close (memfd->fd); - return SSVM_API_ERROR_MMAP; - } - + memfd->fd = alloc.fd; + memfd->sh = alloc.addr; memfd->my_pid = getpid (); + memfd->i_am_master = 1; + + page_size = 1 << alloc.log2_page_size; + sh = (ssvm_shared_header_t *) memfd->sh; sh->master_pid = memfd->my_pid; sh->ssvm_size = memfd->ssvm_size; - sh->heap = mheap_alloc_with_flags - (((u8 *) sh) + MMAP_PAGESIZE, memfd->ssvm_size - MMAP_PAGESIZE, - MHEAP_FLAG_DISABLE_VM | MHEAP_FLAG_THREAD_SAFE); - + sh->heap = mheap_alloc_with_flags (((u8 *) sh) + page_size, + memfd->ssvm_size - page_size, flags); sh->ssvm_va = pointer_to_uword (sh); sh->master_index = master_index; @@ -268,8 +244,6 @@ ssvm_master_init_memfd (ssvm_private_t * memfd, u32 master_index) sh->name = format (0, "%s%c", memfd->name, 0); ssvm_pop_heap (oldheap); - memfd->i_am_master = 1; - /* The application has to set set sh->ready... */ return 0; } @@ -283,39 +257,63 @@ ssvm_master_init_memfd (ssvm_private_t * memfd, u32 master_index) int ssvm_slave_init_memfd (ssvm_private_t * memfd) { + clib_mem_vm_map_t mapa = { 0 }; ssvm_shared_header_t *sh; + uword page_size; memfd->i_am_master = 0; - /* Map the segment once, to look at the shared header */ - sh = (void *) mmap (0, MMAP_PAGESIZE, PROT_READ | PROT_WRITE, MAP_SHARED, - memfd->fd, 0); - if (sh == MAP_FAILED) + page_size = clib_mem_vm_get_page_size (memfd->fd); + if (!page_size) + { + clib_unix_warning ("page size unknown"); + return SSVM_API_ERROR_MMAP; + } + + /* + * Map the segment once, to look at the shared header + */ + mapa.fd = memfd->fd; + mapa.size = page_size; + + if (clib_mem_vm_ext_map (&mapa)) { clib_unix_warning ("slave research mmap"); close (memfd->fd); return SSVM_API_ERROR_MMAP; } - memfd->requested_va = (u64) sh->ssvm_va; + sh = mapa.addr; + memfd->requested_va = sh->ssvm_va; memfd->ssvm_size = sh->ssvm_size; - munmap (sh, MMAP_PAGESIZE); - - sh = (void *) mmap ((void *) memfd->requested_va, memfd->ssvm_size, - PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, - memfd->fd, 0); - - if (sh == MAP_FAILED) + munmap (sh, page_size); + + /* + * Remap the segment at the 'right' address + */ + mapa.requested_va = memfd->requested_va; + mapa.size = memfd->ssvm_size; + if (clib_mem_vm_ext_map (&mapa)) { clib_unix_warning ("slave final mmap"); close (memfd->fd); return SSVM_API_ERROR_MMAP; } + + sh = mapa.addr; sh->slave_pid = getpid (); memfd->sh = sh; return 0; } +void +ssvm_delete_memfd (ssvm_private_t * memfd) +{ + vec_free (memfd->name); + clib_mem_vm_free (memfd->sh, memfd->ssvm_size); + close (memfd->fd); +} + /* * fd.io coding-style-patch-verification: ON * diff --git a/src/svm/ssvm.h b/src/svm/ssvm.h index 0295e302e72..a181f2ef864 100644 --- a/src/svm/ssvm.h +++ b/src/svm/ssvm.h @@ -168,21 +168,7 @@ void ssvm_delete (ssvm_private_t * ssvm); int ssvm_master_init_memfd (ssvm_private_t * memfd, u32 master_index); int ssvm_slave_init_memfd (ssvm_private_t * memfd); -void memfd_delete (ssvm_private_t * memfd); - -/* These do not belong here, but the original keeps running around... */ -/* $$$$ work w/ Damjan to fix properly */ -#ifndef F_LINUX_SPECIFIC_BASE -#define F_LINUX_SPECIFIC_BASE 1024 -#endif -#define MFD_ALLOW_SEALING 0x0002U -#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9) -#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10) - -#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */ -#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */ -#define F_SEAL_GROW 0x0004 /* prevent file from growing */ -#define F_SEAL_WRITE 0x0008 /* prevent writes */ +void ssvm_delete_memfd (ssvm_private_t * memfd); #endif /* __included_ssvm_h__ */ diff --git a/src/svm/svm_fifo_segment.h b/src/svm/svm_fifo_segment.h index 7a30efabdc4..405df934578 100644 --- a/src/svm/svm_fifo_segment.h +++ b/src/svm/svm_fifo_segment.h @@ -15,8 +15,8 @@ #ifndef __included_ssvm_fifo_segment_h__ #define __included_ssvm_fifo_segment_h__ -#include #include +#include #include typedef enum diff --git a/src/vppinfra/linux/mem.c b/src/vppinfra/linux/mem.c index e0e22b0a775..3c449226273 100644 --- a/src/vppinfra/linux/mem.c +++ b/src/vppinfra/linux/mem.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include @@ -45,13 +46,34 @@ #define F_SEAL_WRITE 0x0008 /* prevent writes */ #endif -int -clib_mem_vm_get_log2_page_size (int fd) +uword +clib_mem_vm_get_page_size (int fd) { struct stat st = { 0 }; if (fstat (fd, &st) == -1) return 0; - return min_log2 (st.st_blksize); + return st.st_blksize; +} + +int +clib_mem_vm_get_log2_page_size (int fd) +{ + return min_log2 (clib_mem_vm_get_page_size (fd)); +} + +static void +clib_mem_vm_randomize_va (uword * requested_va, u32 log2_page_size) +{ + u8 bit_mask = 15; + + if (log2_page_size <= 12) + bit_mask = 15; + else if (log2_page_size > 12 && log2_page_size <= 16) + bit_mask = 3; + else + bit_mask = 0; + + *requested_va += (clib_cpu_time_now () & bit_mask) * (1 << log2_page_size); } clib_error_t * @@ -131,13 +153,19 @@ clib_mem_vm_ext_alloc (clib_mem_vm_alloc_t * a) goto error; } } - log2_page_size = clib_mem_vm_get_log2_page_size (fd); + log2_page_size = clib_mem_vm_get_log2_page_size (fd); if (log2_page_size == 0) { err = clib_error_return_unix (0, "cannot determine page size"); goto error; } + + if (a->requested_va) + { + clib_mem_vm_randomize_va (&a->requested_va, log2_page_size); + mmap_flags |= MAP_FIXED; + } } else /* not CLIB_MEM_VM_F_SHARED */ { @@ -155,7 +183,6 @@ clib_mem_vm_ext_alloc (clib_mem_vm_alloc_t * a) n_pages = ((a->size - 1) >> log2_page_size) + 1; - if (a->flags & CLIB_MEM_VM_F_HUGETLB_PREALLOC) { err = clib_sysfs_prealloc_hugepages (a->numa_node, @@ -186,7 +213,8 @@ clib_mem_vm_ext_alloc (clib_mem_vm_alloc_t * a) } } - addr = mmap (0, a->size, (PROT_READ | PROT_WRITE), mmap_flags, fd, 0); + addr = mmap (uword_to_pointer (a->requested_va, void *), a->size, + (PROT_READ | PROT_WRITE), mmap_flags, fd, 0); if (addr == MAP_FAILED) { err = clib_error_return_unix (0, "mmap"); @@ -255,7 +283,24 @@ done: return r; } +clib_error_t * +clib_mem_vm_ext_map (clib_mem_vm_map_t * a) +{ + int mmap_flags = MAP_SHARED; + void *addr; + if (a->requested_va) + mmap_flags |= MAP_FIXED; + + addr = (void *) mmap (uword_to_pointer (a->requested_va, void *), a->size, + PROT_READ | PROT_WRITE, mmap_flags, a->fd, 0); + + if (addr == MAP_FAILED) + return clib_error_return_unix (0, "mmap"); + + a->addr = addr; + return 0; +} /* * fd.io coding-style-patch-verification: ON diff --git a/src/vppinfra/mem.h b/src/vppinfra/mem.h index 69ab880317d..b566e8d8895 100644 --- a/src/vppinfra/mem.h +++ b/src/vppinfra/mem.h @@ -330,7 +330,7 @@ typedef struct #define CLIB_MEM_VM_F_HUGETLB_PREALLOC (1 << 4) u32 flags; /**< vm allocation flags:
CLIB_MEM_VM_F_SHARED: request shared memory, file - destiptor will be provided on successful allocation. + descriptor will be provided on successful allocation.
CLIB_MEM_VM_F_HUGETLB: request hugepages.
CLIB_MEM_VM_F_NUMA_PREFER: numa_node field contains valid numa node preference. @@ -342,15 +342,26 @@ typedef struct uword size; /**< Allocation size, set by caller. */ int numa_node; /**< numa node preference. Valid if CLIB_MEM_VM_F_NUMA_PREFER set. */ void *addr; /**< Pointer to allocated memory, set on successful allocation. */ - int fd; /**< File desriptor, set on successful allocation if CLIB_MEM_VM_F_SHARED is set. */ + int fd; /**< File descriptor, set on successful allocation if CLIB_MEM_VM_F_SHARED is set. */ int log2_page_size; /* Page size in log2 format, set on successful allocation. */ int n_pages; /* Number of pages. */ + uword requested_va; /**< Request fixed position mapping */ } clib_mem_vm_alloc_t; clib_error_t *clib_mem_vm_ext_alloc (clib_mem_vm_alloc_t * a); +u64 clib_mem_vm_get_page_size (int fd); int clib_mem_vm_get_log2_page_size (int fd); u64 *clib_mem_vm_get_paddr (void *mem, int log2_page_size, int n_pages); +typedef struct +{ + uword size; /**< Map size */ + int fd; /**< File descriptor to be mapped */ + uword requested_va; /**< Request fixed position mapping */ + void *addr; /**< Pointer to mapped memory, if successful */ +} clib_mem_vm_map_t; +clib_error_t *clib_mem_vm_ext_map (clib_mem_vm_map_t * a); + #include /* clib_panic */ -- 2.16.6