* [dpdk-dev] [PATCH 0/2] Various fixes for contigmem @ 2017-05-09 8:47 Tiwei Bie 2017-05-09 8:47 ` [dpdk-dev] [PATCH 1/2] contigmem: free the allocated memory when error occurs Tiwei Bie ` (3 more replies) 0 siblings, 4 replies; 13+ messages in thread From: Tiwei Bie @ 2017-05-09 8:47 UTC (permalink / raw) To: dev; +Cc: bruce.richardson Tiwei Bie (2): contigmem: free the allocated memory when error occurs contigmem: don't zero the pages during each mmap lib/librte_eal/bsdapp/contigmem/contigmem.c | 186 ++++++++++++++++++++++++---- 1 file changed, 161 insertions(+), 25 deletions(-) -- 2.12.1 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH 1/2] contigmem: free the allocated memory when error occurs 2017-05-09 8:47 [dpdk-dev] [PATCH 0/2] Various fixes for contigmem Tiwei Bie @ 2017-05-09 8:47 ` Tiwei Bie 2017-05-09 8:47 ` [dpdk-dev] [PATCH 2/2] contigmem: don't zero the pages during each mmap Tiwei Bie ` (2 subsequent siblings) 3 siblings, 0 replies; 13+ messages in thread From: Tiwei Bie @ 2017-05-09 8:47 UTC (permalink / raw) To: dev; +Cc: bruce.richardson, stable Fixes: 764bf26873b9 ("add FreeBSD support") Cc: stable@dpdk.org Signed-off-by: Tiwei Bie <tiwei.bie@intel.com> --- lib/librte_eal/bsdapp/contigmem/contigmem.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/librte_eal/bsdapp/contigmem/contigmem.c b/lib/librte_eal/bsdapp/contigmem/contigmem.c index da971debe..03e3e8def 100644 --- a/lib/librte_eal/bsdapp/contigmem/contigmem.c +++ b/lib/librte_eal/bsdapp/contigmem/contigmem.c @@ -123,19 +123,21 @@ static int contigmem_load() { char index_string[8], description[32]; - int i; + int i, error = 0; if (contigmem_num_buffers > RTE_CONTIGMEM_MAX_NUM_BUFS) { printf("%d buffers requested is greater than %d allowed\n", contigmem_num_buffers, RTE_CONTIGMEM_MAX_NUM_BUFS); - return EINVAL; + error = EINVAL; + goto error; } if (contigmem_buffer_size < PAGE_SIZE || (contigmem_buffer_size & (contigmem_buffer_size - 1)) != 0) { printf("buffer size 0x%lx is not greater than PAGE_SIZE and " "power of two\n", contigmem_buffer_size); - return EINVAL; + error = EINVAL; + goto error; } for (i = 0; i < contigmem_num_buffers; i++) { @@ -145,7 +147,8 @@ contigmem_load() if (contigmem_buffers[i] == NULL) { printf("contigmalloc failed for buffer %d\n", i); - return ENOMEM; + error = ENOMEM; + goto error; } printf("%2u: virt=%p phys=%p\n", i, contigmem_buffers[i], @@ -165,6 +168,14 @@ contigmem_load() GID_WHEEL, 0600, "contigmem"); return 0; + +error: + for (i = 0; i < contigmem_num_buffers; i++) + if (contigmem_buffers[i] != NULL) + contigfree(contigmem_buffers[i], contigmem_buffer_size, + M_CONTIGMEM); + + return error; } static int -- 2.12.1 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH 2/2] contigmem: don't zero the pages during each mmap 2017-05-09 8:47 [dpdk-dev] [PATCH 0/2] Various fixes for contigmem Tiwei Bie 2017-05-09 8:47 ` [dpdk-dev] [PATCH 1/2] contigmem: free the allocated memory when error occurs Tiwei Bie @ 2017-05-09 8:47 ` Tiwei Bie 2017-05-10 14:05 ` [dpdk-dev] [PATCH 0/2] Various fixes for contigmem Richardson, Bruce 2017-05-22 9:03 ` [dpdk-dev] [PATCH v2 " Tiwei Bie 3 siblings, 0 replies; 13+ messages in thread From: Tiwei Bie @ 2017-05-09 8:47 UTC (permalink / raw) To: dev; +Cc: bruce.richardson, stable Don't zero the pages during each mmap. Instead, only zero the pages when they are not already mmapped. Otherwise, the multi-process support will be broken, as the pages will be zeroed when secondary processes map the memory. Besides, track the open and mmap operations on the cdev, and prevent the module from being unloaded when it is still in use. Fixes: 82f931805506 ("contigmem: zero all pages during mmap") Cc: stable@dpdk.org Signed-off-by: Tiwei Bie <tiwei.bie@intel.com> --- lib/librte_eal/bsdapp/contigmem/contigmem.c | 173 ++++++++++++++++++++++++---- 1 file changed, 149 insertions(+), 24 deletions(-) diff --git a/lib/librte_eal/bsdapp/contigmem/contigmem.c b/lib/librte_eal/bsdapp/contigmem/contigmem.c index 03e3e8def..4779a4fa0 100644 --- a/lib/librte_eal/bsdapp/contigmem/contigmem.c +++ b/lib/librte_eal/bsdapp/contigmem/contigmem.c @@ -50,24 +50,37 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> +#include <vm/vm_param.h> #include <vm/vm_object.h> #include <vm/vm_page.h> #include <vm/vm_pager.h> +#include <vm/vm_phys.h> + +struct contigmem_buffer { + void *addr; + int refcnt; + struct mtx mtx; +}; + +struct contigmem_vm_handle { + int buffer_index; +}; static int contigmem_load(void); static int contigmem_unload(void); static int contigmem_physaddr(SYSCTL_HANDLER_ARGS); -static d_mmap_t contigmem_mmap; static d_mmap_single_t contigmem_mmap_single; static d_open_t contigmem_open; +static d_close_t contigmem_close; static int contigmem_num_buffers = RTE_CONTIGMEM_DEFAULT_NUM_BUFS; static int64_t contigmem_buffer_size = RTE_CONTIGMEM_DEFAULT_BUF_SIZE; static eventhandler_tag contigmem_eh_tag; -static void *contigmem_buffers[RTE_CONTIGMEM_MAX_NUM_BUFS]; +static struct contigmem_buffer contigmem_buffers[RTE_CONTIGMEM_MAX_NUM_BUFS]; static struct cdev *contigmem_cdev = NULL; +static int contigmem_refcnt; TUNABLE_INT("hw.contigmem.num_buffers", &contigmem_num_buffers); TUNABLE_QUAD("hw.contigmem.buffer_size", &contigmem_buffer_size); @@ -78,6 +91,8 @@ SYSCTL_INT(_hw_contigmem, OID_AUTO, num_buffers, CTLFLAG_RD, &contigmem_num_buffers, 0, "Number of contigmem buffers allocated"); SYSCTL_QUAD(_hw_contigmem, OID_AUTO, buffer_size, CTLFLAG_RD, &contigmem_buffer_size, 0, "Size of each contiguous buffer"); +SYSCTL_INT(_hw_contigmem, OID_AUTO, num_references, CTLFLAG_RD, + &contigmem_refcnt, 0, "Number of references to contigmem"); static SYSCTL_NODE(_hw_contigmem, OID_AUTO, physaddr, CTLFLAG_RD, 0, "physaddr"); @@ -114,9 +129,10 @@ MODULE_VERSION(contigmem, 1); static struct cdevsw contigmem_ops = { .d_name = "contigmem", .d_version = D_VERSION, - .d_mmap = contigmem_mmap, + .d_flags = D_TRACKCLOSE, .d_mmap_single = contigmem_mmap_single, .d_open = contigmem_open, + .d_close = contigmem_close, }; static int @@ -124,6 +140,7 @@ contigmem_load() { char index_string[8], description[32]; int i, error = 0; + void *addr; if (contigmem_num_buffers > RTE_CONTIGMEM_MAX_NUM_BUFS) { printf("%d buffers requested is greater than %d allowed\n", @@ -141,18 +158,20 @@ contigmem_load() } for (i = 0; i < contigmem_num_buffers; i++) { - contigmem_buffers[i] = - contigmalloc(contigmem_buffer_size, M_CONTIGMEM, M_ZERO, 0, - BUS_SPACE_MAXADDR, contigmem_buffer_size, 0); - - if (contigmem_buffers[i] == NULL) { + addr = contigmalloc(contigmem_buffer_size, M_CONTIGMEM, M_ZERO, + 0, BUS_SPACE_MAXADDR, contigmem_buffer_size, 0); + if (addr == NULL) { printf("contigmalloc failed for buffer %d\n", i); error = ENOMEM; goto error; } - printf("%2u: virt=%p phys=%p\n", i, contigmem_buffers[i], - (void *)pmap_kextract((vm_offset_t)contigmem_buffers[i])); + printf("%2u: virt=%p phys=%p\n", i, addr, + (void *)pmap_kextract((vm_offset_t)addr)); + + mtx_init(&contigmem_buffers[i].mtx, "contigmem", NULL, MTX_DEF); + contigmem_buffers[i].addr = addr; + contigmem_buffers[i].refcnt = 0; snprintf(index_string, sizeof(index_string), "%d", i); snprintf(description, sizeof(description), @@ -171,9 +190,9 @@ contigmem_load() error: for (i = 0; i < contigmem_num_buffers; i++) - if (contigmem_buffers[i] != NULL) - contigfree(contigmem_buffers[i], contigmem_buffer_size, - M_CONTIGMEM); + if (contigmem_buffers[i].addr != NULL) + contigfree(contigmem_buffers[i].addr, + contigmem_buffer_size, M_CONTIGMEM); return error; } @@ -183,6 +202,9 @@ contigmem_unload() { int i; + if (contigmem_refcnt > 0) + return EBUSY; + if (contigmem_cdev != NULL) destroy_dev(contigmem_cdev); @@ -190,9 +212,9 @@ contigmem_unload() EVENTHANDLER_DEREGISTER(process_exit, contigmem_eh_tag); for (i = 0; i < RTE_CONTIGMEM_MAX_NUM_BUFS; i++) - if (contigmem_buffers[i] != NULL) - contigfree(contigmem_buffers[i], contigmem_buffer_size, - M_CONTIGMEM); + if (contigmem_buffers[i].addr != NULL) + contigfree(contigmem_buffers[i].addr, + contigmem_buffer_size, M_CONTIGMEM); return 0; } @@ -203,7 +225,7 @@ contigmem_physaddr(SYSCTL_HANDLER_ARGS) uint64_t physaddr; int index = (int)(uintptr_t)arg1; - physaddr = (uint64_t)vtophys(contigmem_buffers[index]); + physaddr = (uint64_t)vtophys(contigmem_buffers[index].addr); return sysctl_handle_64(oidp, &physaddr, 0, req); } @@ -211,22 +233,118 @@ static int contigmem_open(struct cdev *cdev, int fflags, int devtype, struct thread *td) { + + atomic_add_int(&contigmem_refcnt, 1); + + return 0; +} + +static int +contigmem_close(struct cdev *cdev, int fflags, int devtype, + struct thread *td) +{ + + atomic_subtract_int(&contigmem_refcnt, 1); + return 0; } static int -contigmem_mmap(struct cdev *cdev, vm_ooffset_t offset, vm_paddr_t *paddr, - int prot, vm_memattr_t *memattr) +contigmem_cdev_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot, + vm_ooffset_t foff, struct ucred *cred, u_short *color) { + struct contigmem_vm_handle *vmh = handle; + struct contigmem_buffer *buf; + + buf = &contigmem_buffers[vmh->buffer_index]; + + atomic_add_int(&contigmem_refcnt, 1); + + mtx_lock(&buf->mtx); + if (buf->refcnt == 0) + memset(buf->addr, 0, contigmem_buffer_size); + buf->refcnt++; + mtx_unlock(&buf->mtx); - *paddr = offset; return 0; } +static void +contigmem_cdev_pager_dtor(void *handle) +{ + struct contigmem_vm_handle *vmh = handle; + struct contigmem_buffer *buf; + + buf = &contigmem_buffers[vmh->buffer_index]; + + mtx_lock(&buf->mtx); + buf->refcnt--; + mtx_unlock(&buf->mtx); + + free(vmh, M_CONTIGMEM); + + atomic_subtract_int(&contigmem_refcnt, 1); +} + +static int +contigmem_cdev_pager_fault(vm_object_t object, vm_ooffset_t offset, int prot, + vm_page_t *mres) +{ + vm_paddr_t paddr; + vm_page_t m_paddr, page; + vm_memattr_t memattr, memattr1; + + memattr = object->memattr; + + VM_OBJECT_WUNLOCK(object); + + paddr = offset; + + m_paddr = vm_phys_paddr_to_vm_page(paddr); + if (m_paddr != NULL) { + memattr1 = pmap_page_get_memattr(m_paddr); + if (memattr1 != memattr) + memattr = memattr1; + } + + if (((*mres)->flags & PG_FICTITIOUS) != 0) { + /* + * If the passed in result page is a fake page, update it with + * the new physical address. + */ + page = *mres; + VM_OBJECT_WLOCK(object); + vm_page_updatefake(page, paddr, memattr); + } else { + /* + * Replace the passed in reqpage page with our own fake page and + * free up the all of the original pages. + */ + page = vm_page_getfake(paddr, memattr); + VM_OBJECT_WLOCK(object); + vm_page_replace_checked(page, object, (*mres)->pindex, *mres); + vm_page_lock(*mres); + vm_page_free(*mres); + vm_page_unlock(*mres); + *mres = page; + } + + page->valid = VM_PAGE_BITS_ALL; + + return VM_PAGER_OK; +} + +static struct cdev_pager_ops contigmem_cdev_pager_ops = { + .cdev_pg_ctor = contigmem_cdev_pager_ctor, + .cdev_pg_dtor = contigmem_cdev_pager_dtor, + .cdev_pg_fault = contigmem_cdev_pager_fault, +}; + static int contigmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t size, struct vm_object **obj, int nprot) { + struct contigmem_vm_handle *vmh; uint64_t buffer_index; /* @@ -238,10 +356,17 @@ contigmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t size, if (buffer_index >= contigmem_num_buffers) return EINVAL; - memset(contigmem_buffers[buffer_index], 0, contigmem_buffer_size); - *offset = (vm_ooffset_t)vtophys(contigmem_buffers[buffer_index]); - *obj = vm_pager_allocate(OBJT_DEVICE, cdev, size, nprot, *offset, - curthread->td_ucred); + if (size > contigmem_buffer_size) + return EINVAL; + + vmh = malloc(sizeof(*vmh), M_CONTIGMEM, M_NOWAIT | M_ZERO); + if (vmh == NULL) + return ENOMEM; + vmh->buffer_index = buffer_index; + + *offset = (vm_ooffset_t)vtophys(contigmem_buffers[buffer_index].addr); + *obj = cdev_pager_allocate(vmh, OBJT_DEVICE, &contigmem_cdev_pager_ops, + size, nprot, *offset, curthread->td_ucred); return 0; } -- 2.12.1 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [dpdk-dev] [PATCH 0/2] Various fixes for contigmem 2017-05-09 8:47 [dpdk-dev] [PATCH 0/2] Various fixes for contigmem Tiwei Bie 2017-05-09 8:47 ` [dpdk-dev] [PATCH 1/2] contigmem: free the allocated memory when error occurs Tiwei Bie 2017-05-09 8:47 ` [dpdk-dev] [PATCH 2/2] contigmem: don't zero the pages during each mmap Tiwei Bie @ 2017-05-10 14:05 ` Richardson, Bruce 2017-05-11 1:03 ` Tiwei Bie 2017-05-22 9:03 ` [dpdk-dev] [PATCH v2 " Tiwei Bie 3 siblings, 1 reply; 13+ messages in thread From: Richardson, Bruce @ 2017-05-10 14:05 UTC (permalink / raw) To: Bie, Tiwei, dev > -----Original Message----- > From: Bie, Tiwei > Sent: Tuesday, May 9, 2017 9:47 AM > To: dev@dpdk.org > Cc: Richardson, Bruce <bruce.richardson@intel.com> > Subject: [PATCH 0/2] Various fixes for contigmem > > Tiwei Bie (2): > contigmem: free the allocated memory when error occurs > contigmem: don't zero the pages during each mmap > > lib/librte_eal/bsdapp/contigmem/contigmem.c | 186 > ++++++++++++++++++++++++---- > 1 file changed, 161 insertions(+), 25 deletions(-) > These look better solutions than the previous ones for multi-process. Acked-by: Bruce Richardson <bruce.richardson@intel.com> Given that this is not a new bug in this release, I don't think we should take the risk of applying the patches this late in the 17.05 release cycle. I therefore suggest that they be merged for 17.08 and once tested in that release, backported to 17.05 stable. /Bruce ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [dpdk-dev] [PATCH 0/2] Various fixes for contigmem 2017-05-10 14:05 ` [dpdk-dev] [PATCH 0/2] Various fixes for contigmem Richardson, Bruce @ 2017-05-11 1:03 ` Tiwei Bie 0 siblings, 0 replies; 13+ messages in thread From: Tiwei Bie @ 2017-05-11 1:03 UTC (permalink / raw) To: Richardson, Bruce; +Cc: dev On Wed, May 10, 2017 at 10:05:19PM +0800, Richardson, Bruce wrote: > > > -----Original Message----- > > From: Bie, Tiwei > > Sent: Tuesday, May 9, 2017 9:47 AM > > To: dev@dpdk.org > > Cc: Richardson, Bruce <bruce.richardson@intel.com> > > Subject: [PATCH 0/2] Various fixes for contigmem > > > > Tiwei Bie (2): > > contigmem: free the allocated memory when error occurs > > contigmem: don't zero the pages during each mmap > > > > lib/librte_eal/bsdapp/contigmem/contigmem.c | 186 > > ++++++++++++++++++++++++---- > > 1 file changed, 161 insertions(+), 25 deletions(-) > > > These look better solutions than the previous ones for multi-process. > > Acked-by: Bruce Richardson <bruce.richardson@intel.com> > > Given that this is not a new bug in this release, I don't think we should take the risk of applying the patches this late in the 17.05 release cycle. I therefore suggest that they be merged for 17.08 and once tested in that release, backported to 17.05 stable. > Yeah, I agree. It's not a minor change. Best regards, Tiwei Bie ^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v2 0/2] Various fixes for contigmem 2017-05-09 8:47 [dpdk-dev] [PATCH 0/2] Various fixes for contigmem Tiwei Bie ` (2 preceding siblings ...) 2017-05-10 14:05 ` [dpdk-dev] [PATCH 0/2] Various fixes for contigmem Richardson, Bruce @ 2017-05-22 9:03 ` Tiwei Bie 2017-05-22 9:03 ` [dpdk-dev] [PATCH v2 1/2] contigmem: free the allocated memory when error occurs Tiwei Bie ` (2 more replies) 3 siblings, 3 replies; 13+ messages in thread From: Tiwei Bie @ 2017-05-22 9:03 UTC (permalink / raw) To: dev; +Cc: bruce.richardson Sorry, I just noticed that I forgot to destroy the initialized mtx before failing or unloading. V2 is to fix this issue. --- v2: destroy the initialized mtx before failing or unloading Tiwei Bie (2): contigmem: free the allocated memory when error occurs contigmem: don't zero the pages during each mmap lib/librte_eal/bsdapp/contigmem/contigmem.c | 194 ++++++++++++++++++++++++---- 1 file changed, 168 insertions(+), 26 deletions(-) -- 2.12.1 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v2 1/2] contigmem: free the allocated memory when error occurs 2017-05-22 9:03 ` [dpdk-dev] [PATCH v2 " Tiwei Bie @ 2017-05-22 9:03 ` Tiwei Bie 2017-05-22 9:03 ` [dpdk-dev] [PATCH v2 2/2] contigmem: don't zero the pages during each mmap Tiwei Bie 2017-06-04 5:53 ` [dpdk-dev] [PATCH v3 0/2] Various fixes for contigmem Tiwei Bie 2 siblings, 0 replies; 13+ messages in thread From: Tiwei Bie @ 2017-05-22 9:03 UTC (permalink / raw) To: dev; +Cc: bruce.richardson, stable Fixes: 764bf26873b9 ("add FreeBSD support") Cc: stable@dpdk.org Signed-off-by: Tiwei Bie <tiwei.bie@intel.com> Acked-by: Bruce Richardson <bruce.richardson@intel.com> --- lib/librte_eal/bsdapp/contigmem/contigmem.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/librte_eal/bsdapp/contigmem/contigmem.c b/lib/librte_eal/bsdapp/contigmem/contigmem.c index da971debe..03e3e8def 100644 --- a/lib/librte_eal/bsdapp/contigmem/contigmem.c +++ b/lib/librte_eal/bsdapp/contigmem/contigmem.c @@ -123,19 +123,21 @@ static int contigmem_load() { char index_string[8], description[32]; - int i; + int i, error = 0; if (contigmem_num_buffers > RTE_CONTIGMEM_MAX_NUM_BUFS) { printf("%d buffers requested is greater than %d allowed\n", contigmem_num_buffers, RTE_CONTIGMEM_MAX_NUM_BUFS); - return EINVAL; + error = EINVAL; + goto error; } if (contigmem_buffer_size < PAGE_SIZE || (contigmem_buffer_size & (contigmem_buffer_size - 1)) != 0) { printf("buffer size 0x%lx is not greater than PAGE_SIZE and " "power of two\n", contigmem_buffer_size); - return EINVAL; + error = EINVAL; + goto error; } for (i = 0; i < contigmem_num_buffers; i++) { @@ -145,7 +147,8 @@ contigmem_load() if (contigmem_buffers[i] == NULL) { printf("contigmalloc failed for buffer %d\n", i); - return ENOMEM; + error = ENOMEM; + goto error; } printf("%2u: virt=%p phys=%p\n", i, contigmem_buffers[i], @@ -165,6 +168,14 @@ contigmem_load() GID_WHEEL, 0600, "contigmem"); return 0; + +error: + for (i = 0; i < contigmem_num_buffers; i++) + if (contigmem_buffers[i] != NULL) + contigfree(contigmem_buffers[i], contigmem_buffer_size, + M_CONTIGMEM); + + return error; } static int -- 2.12.1 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v2 2/2] contigmem: don't zero the pages during each mmap 2017-05-22 9:03 ` [dpdk-dev] [PATCH v2 " Tiwei Bie 2017-05-22 9:03 ` [dpdk-dev] [PATCH v2 1/2] contigmem: free the allocated memory when error occurs Tiwei Bie @ 2017-05-22 9:03 ` Tiwei Bie 2017-05-22 10:15 ` [dpdk-dev] [dpdk-stable] " Shahaf Shuler 2017-06-04 5:53 ` [dpdk-dev] [PATCH v3 0/2] Various fixes for contigmem Tiwei Bie 2 siblings, 1 reply; 13+ messages in thread From: Tiwei Bie @ 2017-05-22 9:03 UTC (permalink / raw) To: dev; +Cc: bruce.richardson, stable Don't zero the pages during each mmap. Instead, only zero the pages when they are not already mmapped. Otherwise, the multi-process support will be broken, as the pages will be zeroed when secondary processes map the memory. Besides, track the open and mmap operations on the cdev, and prevent the module from being unloaded when it is still in use. Fixes: 82f931805506 ("contigmem: zero all pages during mmap") Cc: stable@dpdk.org Signed-off-by: Tiwei Bie <tiwei.bie@intel.com> Acked-by: Bruce Richardson <bruce.richardson@intel.com> --- lib/librte_eal/bsdapp/contigmem/contigmem.c | 183 ++++++++++++++++++++++++---- 1 file changed, 157 insertions(+), 26 deletions(-) diff --git a/lib/librte_eal/bsdapp/contigmem/contigmem.c b/lib/librte_eal/bsdapp/contigmem/contigmem.c index 03e3e8def..b201d7bf4 100644 --- a/lib/librte_eal/bsdapp/contigmem/contigmem.c +++ b/lib/librte_eal/bsdapp/contigmem/contigmem.c @@ -50,24 +50,37 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> +#include <vm/vm_param.h> #include <vm/vm_object.h> #include <vm/vm_page.h> #include <vm/vm_pager.h> +#include <vm/vm_phys.h> + +struct contigmem_buffer { + void *addr; + int refcnt; + struct mtx mtx; +}; + +struct contigmem_vm_handle { + int buffer_index; +}; static int contigmem_load(void); static int contigmem_unload(void); static int contigmem_physaddr(SYSCTL_HANDLER_ARGS); -static d_mmap_t contigmem_mmap; static d_mmap_single_t contigmem_mmap_single; static d_open_t contigmem_open; +static d_close_t contigmem_close; static int contigmem_num_buffers = RTE_CONTIGMEM_DEFAULT_NUM_BUFS; static int64_t contigmem_buffer_size = RTE_CONTIGMEM_DEFAULT_BUF_SIZE; static eventhandler_tag contigmem_eh_tag; -static void *contigmem_buffers[RTE_CONTIGMEM_MAX_NUM_BUFS]; +static struct contigmem_buffer contigmem_buffers[RTE_CONTIGMEM_MAX_NUM_BUFS]; static struct cdev *contigmem_cdev = NULL; +static int contigmem_refcnt; TUNABLE_INT("hw.contigmem.num_buffers", &contigmem_num_buffers); TUNABLE_QUAD("hw.contigmem.buffer_size", &contigmem_buffer_size); @@ -78,6 +91,8 @@ SYSCTL_INT(_hw_contigmem, OID_AUTO, num_buffers, CTLFLAG_RD, &contigmem_num_buffers, 0, "Number of contigmem buffers allocated"); SYSCTL_QUAD(_hw_contigmem, OID_AUTO, buffer_size, CTLFLAG_RD, &contigmem_buffer_size, 0, "Size of each contiguous buffer"); +SYSCTL_INT(_hw_contigmem, OID_AUTO, num_references, CTLFLAG_RD, + &contigmem_refcnt, 0, "Number of references to contigmem"); static SYSCTL_NODE(_hw_contigmem, OID_AUTO, physaddr, CTLFLAG_RD, 0, "physaddr"); @@ -114,9 +129,10 @@ MODULE_VERSION(contigmem, 1); static struct cdevsw contigmem_ops = { .d_name = "contigmem", .d_version = D_VERSION, - .d_mmap = contigmem_mmap, + .d_flags = D_TRACKCLOSE, .d_mmap_single = contigmem_mmap_single, .d_open = contigmem_open, + .d_close = contigmem_close, }; static int @@ -124,6 +140,7 @@ contigmem_load() { char index_string[8], description[32]; int i, error = 0; + void *addr; if (contigmem_num_buffers > RTE_CONTIGMEM_MAX_NUM_BUFS) { printf("%d buffers requested is greater than %d allowed\n", @@ -141,18 +158,20 @@ contigmem_load() } for (i = 0; i < contigmem_num_buffers; i++) { - contigmem_buffers[i] = - contigmalloc(contigmem_buffer_size, M_CONTIGMEM, M_ZERO, 0, - BUS_SPACE_MAXADDR, contigmem_buffer_size, 0); - - if (contigmem_buffers[i] == NULL) { + addr = contigmalloc(contigmem_buffer_size, M_CONTIGMEM, M_ZERO, + 0, BUS_SPACE_MAXADDR, contigmem_buffer_size, 0); + if (addr == NULL) { printf("contigmalloc failed for buffer %d\n", i); error = ENOMEM; goto error; } - printf("%2u: virt=%p phys=%p\n", i, contigmem_buffers[i], - (void *)pmap_kextract((vm_offset_t)contigmem_buffers[i])); + printf("%2u: virt=%p phys=%p\n", i, addr, + (void *)pmap_kextract((vm_offset_t)addr)); + + mtx_init(&contigmem_buffers[i].mtx, "contigmem", NULL, MTX_DEF); + contigmem_buffers[i].addr = addr; + contigmem_buffers[i].refcnt = 0; snprintf(index_string, sizeof(index_string), "%d", i); snprintf(description, sizeof(description), @@ -170,10 +189,13 @@ contigmem_load() return 0; error: - for (i = 0; i < contigmem_num_buffers; i++) - if (contigmem_buffers[i] != NULL) - contigfree(contigmem_buffers[i], contigmem_buffer_size, - M_CONTIGMEM); + for (i = 0; i < contigmem_num_buffers; i++) { + if (contigmem_buffers[i].addr != NULL) + contigfree(contigmem_buffers[i].addr, + contigmem_buffer_size, M_CONTIGMEM); + if (mtx_initialized(&contigmem_buffers[i].mtx)) + mtx_destroy(&contigmem_buffers[i].mtx); + } return error; } @@ -183,16 +205,22 @@ contigmem_unload() { int i; + if (contigmem_refcnt > 0) + return EBUSY; + if (contigmem_cdev != NULL) destroy_dev(contigmem_cdev); if (contigmem_eh_tag != NULL) EVENTHANDLER_DEREGISTER(process_exit, contigmem_eh_tag); - for (i = 0; i < RTE_CONTIGMEM_MAX_NUM_BUFS; i++) - if (contigmem_buffers[i] != NULL) - contigfree(contigmem_buffers[i], contigmem_buffer_size, - M_CONTIGMEM); + for (i = 0; i < RTE_CONTIGMEM_MAX_NUM_BUFS; i++) { + if (contigmem_buffers[i].addr != NULL) + contigfree(contigmem_buffers[i].addr, + contigmem_buffer_size, M_CONTIGMEM); + if (mtx_initialized(&contigmem_buffers[i].mtx)) + mtx_destroy(&contigmem_buffers[i].mtx); + } return 0; } @@ -203,7 +231,7 @@ contigmem_physaddr(SYSCTL_HANDLER_ARGS) uint64_t physaddr; int index = (int)(uintptr_t)arg1; - physaddr = (uint64_t)vtophys(contigmem_buffers[index]); + physaddr = (uint64_t)vtophys(contigmem_buffers[index].addr); return sysctl_handle_64(oidp, &physaddr, 0, req); } @@ -211,22 +239,118 @@ static int contigmem_open(struct cdev *cdev, int fflags, int devtype, struct thread *td) { + + atomic_add_int(&contigmem_refcnt, 1); + + return 0; +} + +static int +contigmem_close(struct cdev *cdev, int fflags, int devtype, + struct thread *td) +{ + + atomic_subtract_int(&contigmem_refcnt, 1); + return 0; } static int -contigmem_mmap(struct cdev *cdev, vm_ooffset_t offset, vm_paddr_t *paddr, - int prot, vm_memattr_t *memattr) +contigmem_cdev_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot, + vm_ooffset_t foff, struct ucred *cred, u_short *color) { + struct contigmem_vm_handle *vmh = handle; + struct contigmem_buffer *buf; + + buf = &contigmem_buffers[vmh->buffer_index]; + + atomic_add_int(&contigmem_refcnt, 1); + + mtx_lock(&buf->mtx); + if (buf->refcnt == 0) + memset(buf->addr, 0, contigmem_buffer_size); + buf->refcnt++; + mtx_unlock(&buf->mtx); - *paddr = offset; return 0; } +static void +contigmem_cdev_pager_dtor(void *handle) +{ + struct contigmem_vm_handle *vmh = handle; + struct contigmem_buffer *buf; + + buf = &contigmem_buffers[vmh->buffer_index]; + + mtx_lock(&buf->mtx); + buf->refcnt--; + mtx_unlock(&buf->mtx); + + free(vmh, M_CONTIGMEM); + + atomic_subtract_int(&contigmem_refcnt, 1); +} + +static int +contigmem_cdev_pager_fault(vm_object_t object, vm_ooffset_t offset, int prot, + vm_page_t *mres) +{ + vm_paddr_t paddr; + vm_page_t m_paddr, page; + vm_memattr_t memattr, memattr1; + + memattr = object->memattr; + + VM_OBJECT_WUNLOCK(object); + + paddr = offset; + + m_paddr = vm_phys_paddr_to_vm_page(paddr); + if (m_paddr != NULL) { + memattr1 = pmap_page_get_memattr(m_paddr); + if (memattr1 != memattr) + memattr = memattr1; + } + + if (((*mres)->flags & PG_FICTITIOUS) != 0) { + /* + * If the passed in result page is a fake page, update it with + * the new physical address. + */ + page = *mres; + VM_OBJECT_WLOCK(object); + vm_page_updatefake(page, paddr, memattr); + } else { + /* + * Replace the passed in reqpage page with our own fake page and + * free up the all of the original pages. + */ + page = vm_page_getfake(paddr, memattr); + VM_OBJECT_WLOCK(object); + vm_page_replace_checked(page, object, (*mres)->pindex, *mres); + vm_page_lock(*mres); + vm_page_free(*mres); + vm_page_unlock(*mres); + *mres = page; + } + + page->valid = VM_PAGE_BITS_ALL; + + return VM_PAGER_OK; +} + +static struct cdev_pager_ops contigmem_cdev_pager_ops = { + .cdev_pg_ctor = contigmem_cdev_pager_ctor, + .cdev_pg_dtor = contigmem_cdev_pager_dtor, + .cdev_pg_fault = contigmem_cdev_pager_fault, +}; + static int contigmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t size, struct vm_object **obj, int nprot) { + struct contigmem_vm_handle *vmh; uint64_t buffer_index; /* @@ -238,10 +362,17 @@ contigmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t size, if (buffer_index >= contigmem_num_buffers) return EINVAL; - memset(contigmem_buffers[buffer_index], 0, contigmem_buffer_size); - *offset = (vm_ooffset_t)vtophys(contigmem_buffers[buffer_index]); - *obj = vm_pager_allocate(OBJT_DEVICE, cdev, size, nprot, *offset, - curthread->td_ucred); + if (size > contigmem_buffer_size) + return EINVAL; + + vmh = malloc(sizeof(*vmh), M_CONTIGMEM, M_NOWAIT | M_ZERO); + if (vmh == NULL) + return ENOMEM; + vmh->buffer_index = buffer_index; + + *offset = (vm_ooffset_t)vtophys(contigmem_buffers[buffer_index].addr); + *obj = cdev_pager_allocate(vmh, OBJT_DEVICE, &contigmem_cdev_pager_ops, + size, nprot, *offset, curthread->td_ucred); return 0; } -- 2.12.1 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [dpdk-dev] [dpdk-stable] [PATCH v2 2/2] contigmem: don't zero the pages during each mmap 2017-05-22 9:03 ` [dpdk-dev] [PATCH v2 2/2] contigmem: don't zero the pages during each mmap Tiwei Bie @ 2017-05-22 10:15 ` Shahaf Shuler 0 siblings, 0 replies; 13+ messages in thread From: Shahaf Shuler @ 2017-05-22 10:15 UTC (permalink / raw) To: Tiwei Bie, dev, Nélio Laranjeiro, Adrien Mazarguil, Olga Shern Cc: bruce.richardson, stable Nélio, related to the issue you saw with secondary process support? --Shahaf Monday, May 22, 2017 12:04 PM, Tiwei Bie: > Don't zero the pages during each mmap. Instead, only zero the pages when > they are not already mmapped. Otherwise, the multi-process support will be > broken, as the pages will be zeroed when secondary processes map the > memory. Besides, track the open and mmap operations on the cdev, and > prevent the module from being unloaded when it is still in use. > > Fixes: 82f931805506 ("contigmem: zero all pages during mmap") > Cc: stable@dpdk.org > > Signed-off-by: Tiwei Bie <tiwei.bie@intel.com> > Acked-by: Bruce Richardson <bruce.richardson@intel.com> > --- > lib/librte_eal/bsdapp/contigmem/contigmem.c | 183 > ++++++++++++++++++++++++---- > 1 file changed, 157 insertions(+), 26 deletions(-) > > diff --git a/lib/librte_eal/bsdapp/contigmem/contigmem.c > b/lib/librte_eal/bsdapp/contigmem/contigmem.c > index 03e3e8def..b201d7bf4 100644 > --- a/lib/librte_eal/bsdapp/contigmem/contigmem.c > +++ b/lib/librte_eal/bsdapp/contigmem/contigmem.c > @@ -50,24 +50,37 @@ __FBSDID("$FreeBSD$"); > > #include <vm/vm.h> > #include <vm/pmap.h> > +#include <vm/vm_param.h> > #include <vm/vm_object.h> > #include <vm/vm_page.h> > #include <vm/vm_pager.h> > +#include <vm/vm_phys.h> > + > +struct contigmem_buffer { > + void *addr; > + int refcnt; > + struct mtx mtx; > +}; > + > +struct contigmem_vm_handle { > + int buffer_index; > +}; > > static int contigmem_load(void); > static int contigmem_unload(void); > static int contigmem_physaddr(SYSCTL_HANDLER_ARGS); > > -static d_mmap_t contigmem_mmap; > static d_mmap_single_t contigmem_mmap_single; > static d_open_t contigmem_open; > +static d_close_t contigmem_close; > > static int contigmem_num_buffers = > RTE_CONTIGMEM_DEFAULT_NUM_BUFS; > static int64_t contigmem_buffer_size = > RTE_CONTIGMEM_DEFAULT_BUF_SIZE; > > static eventhandler_tag contigmem_eh_tag; > -static void > *contigmem_buffers[RTE_CONTIGMEM_MAX_NUM_BUFS]; > +static struct contigmem_buffer > +contigmem_buffers[RTE_CONTIGMEM_MAX_NUM_BUFS]; > static struct cdev *contigmem_cdev = NULL; > +static int contigmem_refcnt; > > TUNABLE_INT("hw.contigmem.num_buffers", &contigmem_num_buffers); > TUNABLE_QUAD("hw.contigmem.buffer_size", &contigmem_buffer_size); > @@ -78,6 +91,8 @@ SYSCTL_INT(_hw_contigmem, OID_AUTO, > num_buffers, CTLFLAG_RD, > &contigmem_num_buffers, 0, "Number of contigmem buffers > allocated"); SYSCTL_QUAD(_hw_contigmem, OID_AUTO, buffer_size, > CTLFLAG_RD, > &contigmem_buffer_size, 0, "Size of each contiguous buffer"); > +SYSCTL_INT(_hw_contigmem, OID_AUTO, num_references, CTLFLAG_RD, > + &contigmem_refcnt, 0, "Number of references to contigmem"); > > static SYSCTL_NODE(_hw_contigmem, OID_AUTO, physaddr, CTLFLAG_RD, > 0, > "physaddr"); > @@ -114,9 +129,10 @@ MODULE_VERSION(contigmem, 1); static struct > cdevsw contigmem_ops = { > .d_name = "contigmem", > .d_version = D_VERSION, > - .d_mmap = contigmem_mmap, > + .d_flags = D_TRACKCLOSE, > .d_mmap_single = contigmem_mmap_single, > .d_open = contigmem_open, > + .d_close = contigmem_close, > }; > > static int > @@ -124,6 +140,7 @@ contigmem_load() > { > char index_string[8], description[32]; > int i, error = 0; > + void *addr; > > if (contigmem_num_buffers > > RTE_CONTIGMEM_MAX_NUM_BUFS) { > printf("%d buffers requested is greater than %d allowed\n", > @@ -141,18 +158,20 @@ contigmem_load() > } > > for (i = 0; i < contigmem_num_buffers; i++) { > - contigmem_buffers[i] = > - contigmalloc(contigmem_buffer_size, > M_CONTIGMEM, M_ZERO, 0, > - BUS_SPACE_MAXADDR, contigmem_buffer_size, 0); > - > - if (contigmem_buffers[i] == NULL) { > + addr = contigmalloc(contigmem_buffer_size, > M_CONTIGMEM, M_ZERO, > + 0, BUS_SPACE_MAXADDR, contigmem_buffer_size, > 0); > + if (addr == NULL) { > printf("contigmalloc failed for buffer %d\n", i); > error = ENOMEM; > goto error; > } > > - printf("%2u: virt=%p phys=%p\n", i, contigmem_buffers[i], > - (void > *)pmap_kextract((vm_offset_t)contigmem_buffers[i])); > + printf("%2u: virt=%p phys=%p\n", i, addr, > + (void *)pmap_kextract((vm_offset_t)addr)); > + > + mtx_init(&contigmem_buffers[i].mtx, "contigmem", NULL, > MTX_DEF); > + contigmem_buffers[i].addr = addr; > + contigmem_buffers[i].refcnt = 0; > > snprintf(index_string, sizeof(index_string), "%d", i); > snprintf(description, sizeof(description), @@ -170,10 +189,13 > @@ contigmem_load() > return 0; > > error: > - for (i = 0; i < contigmem_num_buffers; i++) > - if (contigmem_buffers[i] != NULL) > - contigfree(contigmem_buffers[i], > contigmem_buffer_size, > - M_CONTIGMEM); > + for (i = 0; i < contigmem_num_buffers; i++) { > + if (contigmem_buffers[i].addr != NULL) > + contigfree(contigmem_buffers[i].addr, > + contigmem_buffer_size, M_CONTIGMEM); > + if (mtx_initialized(&contigmem_buffers[i].mtx)) > + mtx_destroy(&contigmem_buffers[i].mtx); > + } > > return error; > } > @@ -183,16 +205,22 @@ contigmem_unload() { > int i; > > + if (contigmem_refcnt > 0) > + return EBUSY; > + > if (contigmem_cdev != NULL) > destroy_dev(contigmem_cdev); > > if (contigmem_eh_tag != NULL) > EVENTHANDLER_DEREGISTER(process_exit, > contigmem_eh_tag); > > - for (i = 0; i < RTE_CONTIGMEM_MAX_NUM_BUFS; i++) > - if (contigmem_buffers[i] != NULL) > - contigfree(contigmem_buffers[i], > contigmem_buffer_size, > - M_CONTIGMEM); > + for (i = 0; i < RTE_CONTIGMEM_MAX_NUM_BUFS; i++) { > + if (contigmem_buffers[i].addr != NULL) > + contigfree(contigmem_buffers[i].addr, > + contigmem_buffer_size, M_CONTIGMEM); > + if (mtx_initialized(&contigmem_buffers[i].mtx)) > + mtx_destroy(&contigmem_buffers[i].mtx); > + } > > return 0; > } > @@ -203,7 +231,7 @@ contigmem_physaddr(SYSCTL_HANDLER_ARGS) > uint64_t physaddr; > int index = (int)(uintptr_t)arg1; > > - physaddr = (uint64_t)vtophys(contigmem_buffers[index]); > + physaddr = (uint64_t)vtophys(contigmem_buffers[index].addr); > return sysctl_handle_64(oidp, &physaddr, 0, req); } > > @@ -211,22 +239,118 @@ static int > contigmem_open(struct cdev *cdev, int fflags, int devtype, > struct thread *td) > { > + > + atomic_add_int(&contigmem_refcnt, 1); > + > + return 0; > +} > + > +static int > +contigmem_close(struct cdev *cdev, int fflags, int devtype, > + struct thread *td) > +{ > + > + atomic_subtract_int(&contigmem_refcnt, 1); > + > return 0; > } > > static int > -contigmem_mmap(struct cdev *cdev, vm_ooffset_t offset, vm_paddr_t > *paddr, > - int prot, vm_memattr_t *memattr) > +contigmem_cdev_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t > prot, > + vm_ooffset_t foff, struct ucred *cred, u_short *color) > { > + struct contigmem_vm_handle *vmh = handle; > + struct contigmem_buffer *buf; > + > + buf = &contigmem_buffers[vmh->buffer_index]; > + > + atomic_add_int(&contigmem_refcnt, 1); > + > + mtx_lock(&buf->mtx); > + if (buf->refcnt == 0) > + memset(buf->addr, 0, contigmem_buffer_size); > + buf->refcnt++; > + mtx_unlock(&buf->mtx); > > - *paddr = offset; > return 0; > } > > +static void > +contigmem_cdev_pager_dtor(void *handle) { > + struct contigmem_vm_handle *vmh = handle; > + struct contigmem_buffer *buf; > + > + buf = &contigmem_buffers[vmh->buffer_index]; > + > + mtx_lock(&buf->mtx); > + buf->refcnt--; > + mtx_unlock(&buf->mtx); > + > + free(vmh, M_CONTIGMEM); > + > + atomic_subtract_int(&contigmem_refcnt, 1); } > + > +static int > +contigmem_cdev_pager_fault(vm_object_t object, vm_ooffset_t offset, > int prot, > + vm_page_t *mres) > +{ > + vm_paddr_t paddr; > + vm_page_t m_paddr, page; > + vm_memattr_t memattr, memattr1; > + > + memattr = object->memattr; > + > + VM_OBJECT_WUNLOCK(object); > + > + paddr = offset; > + > + m_paddr = vm_phys_paddr_to_vm_page(paddr); > + if (m_paddr != NULL) { > + memattr1 = pmap_page_get_memattr(m_paddr); > + if (memattr1 != memattr) > + memattr = memattr1; > + } > + > + if (((*mres)->flags & PG_FICTITIOUS) != 0) { > + /* > + * If the passed in result page is a fake page, update it with > + * the new physical address. > + */ > + page = *mres; > + VM_OBJECT_WLOCK(object); > + vm_page_updatefake(page, paddr, memattr); > + } else { > + /* > + * Replace the passed in reqpage page with our own fake > page and > + * free up the all of the original pages. > + */ > + page = vm_page_getfake(paddr, memattr); > + VM_OBJECT_WLOCK(object); > + vm_page_replace_checked(page, object, (*mres)->pindex, > *mres); > + vm_page_lock(*mres); > + vm_page_free(*mres); > + vm_page_unlock(*mres); > + *mres = page; > + } > + > + page->valid = VM_PAGE_BITS_ALL; > + > + return VM_PAGER_OK; > +} > + > +static struct cdev_pager_ops contigmem_cdev_pager_ops = { > + .cdev_pg_ctor = contigmem_cdev_pager_ctor, > + .cdev_pg_dtor = contigmem_cdev_pager_dtor, > + .cdev_pg_fault = contigmem_cdev_pager_fault, }; > + > static int > contigmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, > vm_size_t size, > struct vm_object **obj, int nprot) > { > + struct contigmem_vm_handle *vmh; > uint64_t buffer_index; > > /* > @@ -238,10 +362,17 @@ contigmem_mmap_single(struct cdev *cdev, > vm_ooffset_t *offset, vm_size_t size, > if (buffer_index >= contigmem_num_buffers) > return EINVAL; > > - memset(contigmem_buffers[buffer_index], 0, > contigmem_buffer_size); > - *offset = > (vm_ooffset_t)vtophys(contigmem_buffers[buffer_index]); > - *obj = vm_pager_allocate(OBJT_DEVICE, cdev, size, nprot, *offset, > - curthread->td_ucred); > + if (size > contigmem_buffer_size) > + return EINVAL; > + > + vmh = malloc(sizeof(*vmh), M_CONTIGMEM, M_NOWAIT | > M_ZERO); > + if (vmh == NULL) > + return ENOMEM; > + vmh->buffer_index = buffer_index; > + > + *offset = > (vm_ooffset_t)vtophys(contigmem_buffers[buffer_index].addr); > + *obj = cdev_pager_allocate(vmh, OBJT_DEVICE, > &contigmem_cdev_pager_ops, > + size, nprot, *offset, curthread->td_ucred); > > return 0; > } > -- > 2.12.1 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v3 0/2] Various fixes for contigmem 2017-05-22 9:03 ` [dpdk-dev] [PATCH v2 " Tiwei Bie 2017-05-22 9:03 ` [dpdk-dev] [PATCH v2 1/2] contigmem: free the allocated memory when error occurs Tiwei Bie 2017-05-22 9:03 ` [dpdk-dev] [PATCH v2 2/2] contigmem: don't zero the pages during each mmap Tiwei Bie @ 2017-06-04 5:53 ` Tiwei Bie 2017-06-04 5:53 ` [dpdk-dev] [PATCH v3 1/2] contigmem: free the allocated memory when error occurs Tiwei Bie ` (2 more replies) 2 siblings, 3 replies; 13+ messages in thread From: Tiwei Bie @ 2017-06-04 5:53 UTC (permalink / raw) To: dev; +Cc: bruce.richardson The vm_page_replace_checked() was introduced in FreeBSD 11, so the build is broken on FreeBSD 10. The fix is to use vm_page_replace() directly and do the check in caller. --- v2: destroy the initialized mtx before failing or unloading v3: fix build on FreeBSD 10, refine comments Tiwei Bie (2): contigmem: free the allocated memory when error occurs contigmem: don't zero the pages during each mmap lib/librte_eal/bsdapp/contigmem/contigmem.c | 197 ++++++++++++++++++++++++---- 1 file changed, 171 insertions(+), 26 deletions(-) -- 2.12.1 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v3 1/2] contigmem: free the allocated memory when error occurs 2017-06-04 5:53 ` [dpdk-dev] [PATCH v3 0/2] Various fixes for contigmem Tiwei Bie @ 2017-06-04 5:53 ` Tiwei Bie 2017-06-04 5:53 ` [dpdk-dev] [PATCH v3 2/2] contigmem: don't zero the pages during each mmap Tiwei Bie 2017-07-03 23:33 ` [dpdk-dev] [PATCH v3 0/2] Various fixes for contigmem Thomas Monjalon 2 siblings, 0 replies; 13+ messages in thread From: Tiwei Bie @ 2017-06-04 5:53 UTC (permalink / raw) To: dev; +Cc: bruce.richardson, stable Fixes: 764bf26873b9 ("add FreeBSD support") Cc: stable@dpdk.org Signed-off-by: Tiwei Bie <tiwei.bie@intel.com> Acked-by: Bruce Richardson <bruce.richardson@intel.com> --- lib/librte_eal/bsdapp/contigmem/contigmem.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/lib/librte_eal/bsdapp/contigmem/contigmem.c b/lib/librte_eal/bsdapp/contigmem/contigmem.c index da971debe..03e3e8def 100644 --- a/lib/librte_eal/bsdapp/contigmem/contigmem.c +++ b/lib/librte_eal/bsdapp/contigmem/contigmem.c @@ -123,19 +123,21 @@ static int contigmem_load() { char index_string[8], description[32]; - int i; + int i, error = 0; if (contigmem_num_buffers > RTE_CONTIGMEM_MAX_NUM_BUFS) { printf("%d buffers requested is greater than %d allowed\n", contigmem_num_buffers, RTE_CONTIGMEM_MAX_NUM_BUFS); - return EINVAL; + error = EINVAL; + goto error; } if (contigmem_buffer_size < PAGE_SIZE || (contigmem_buffer_size & (contigmem_buffer_size - 1)) != 0) { printf("buffer size 0x%lx is not greater than PAGE_SIZE and " "power of two\n", contigmem_buffer_size); - return EINVAL; + error = EINVAL; + goto error; } for (i = 0; i < contigmem_num_buffers; i++) { @@ -145,7 +147,8 @@ contigmem_load() if (contigmem_buffers[i] == NULL) { printf("contigmalloc failed for buffer %d\n", i); - return ENOMEM; + error = ENOMEM; + goto error; } printf("%2u: virt=%p phys=%p\n", i, contigmem_buffers[i], @@ -165,6 +168,14 @@ contigmem_load() GID_WHEEL, 0600, "contigmem"); return 0; + +error: + for (i = 0; i < contigmem_num_buffers; i++) + if (contigmem_buffers[i] != NULL) + contigfree(contigmem_buffers[i], contigmem_buffer_size, + M_CONTIGMEM); + + return error; } static int -- 2.13.0 ^ permalink raw reply [flat|nested] 13+ messages in thread
* [dpdk-dev] [PATCH v3 2/2] contigmem: don't zero the pages during each mmap 2017-06-04 5:53 ` [dpdk-dev] [PATCH v3 0/2] Various fixes for contigmem Tiwei Bie 2017-06-04 5:53 ` [dpdk-dev] [PATCH v3 1/2] contigmem: free the allocated memory when error occurs Tiwei Bie @ 2017-06-04 5:53 ` Tiwei Bie 2017-07-03 23:33 ` [dpdk-dev] [PATCH v3 0/2] Various fixes for contigmem Thomas Monjalon 2 siblings, 0 replies; 13+ messages in thread From: Tiwei Bie @ 2017-06-04 5:53 UTC (permalink / raw) To: dev; +Cc: bruce.richardson, stable Don't zero the pages during each mmap. Instead, only zero the pages when they are not already mmapped. Otherwise, the multi-process support will be broken, as the pages will be zeroed when secondary processes map the memory. Besides, track the open and mmap operations on the cdev, and prevent the module from being unloaded when it is still in use. Fixes: 82f931805506 ("contigmem: zero all pages during mmap") Cc: stable@dpdk.org Signed-off-by: Tiwei Bie <tiwei.bie@intel.com> Acked-by: Bruce Richardson <bruce.richardson@intel.com> --- lib/librte_eal/bsdapp/contigmem/contigmem.c | 186 ++++++++++++++++++++++++---- 1 file changed, 160 insertions(+), 26 deletions(-) diff --git a/lib/librte_eal/bsdapp/contigmem/contigmem.c b/lib/librte_eal/bsdapp/contigmem/contigmem.c index 03e3e8def..e8fb9087d 100644 --- a/lib/librte_eal/bsdapp/contigmem/contigmem.c +++ b/lib/librte_eal/bsdapp/contigmem/contigmem.c @@ -50,24 +50,37 @@ __FBSDID("$FreeBSD$"); #include <vm/vm.h> #include <vm/pmap.h> +#include <vm/vm_param.h> #include <vm/vm_object.h> #include <vm/vm_page.h> #include <vm/vm_pager.h> +#include <vm/vm_phys.h> + +struct contigmem_buffer { + void *addr; + int refcnt; + struct mtx mtx; +}; + +struct contigmem_vm_handle { + int buffer_index; +}; static int contigmem_load(void); static int contigmem_unload(void); static int contigmem_physaddr(SYSCTL_HANDLER_ARGS); -static d_mmap_t contigmem_mmap; static d_mmap_single_t contigmem_mmap_single; static d_open_t contigmem_open; +static d_close_t contigmem_close; static int contigmem_num_buffers = RTE_CONTIGMEM_DEFAULT_NUM_BUFS; static int64_t contigmem_buffer_size = RTE_CONTIGMEM_DEFAULT_BUF_SIZE; static eventhandler_tag contigmem_eh_tag; -static void *contigmem_buffers[RTE_CONTIGMEM_MAX_NUM_BUFS]; +static struct contigmem_buffer contigmem_buffers[RTE_CONTIGMEM_MAX_NUM_BUFS]; static struct cdev *contigmem_cdev = NULL; +static int contigmem_refcnt; TUNABLE_INT("hw.contigmem.num_buffers", &contigmem_num_buffers); TUNABLE_QUAD("hw.contigmem.buffer_size", &contigmem_buffer_size); @@ -78,6 +91,8 @@ SYSCTL_INT(_hw_contigmem, OID_AUTO, num_buffers, CTLFLAG_RD, &contigmem_num_buffers, 0, "Number of contigmem buffers allocated"); SYSCTL_QUAD(_hw_contigmem, OID_AUTO, buffer_size, CTLFLAG_RD, &contigmem_buffer_size, 0, "Size of each contiguous buffer"); +SYSCTL_INT(_hw_contigmem, OID_AUTO, num_references, CTLFLAG_RD, + &contigmem_refcnt, 0, "Number of references to contigmem"); static SYSCTL_NODE(_hw_contigmem, OID_AUTO, physaddr, CTLFLAG_RD, 0, "physaddr"); @@ -114,9 +129,10 @@ MODULE_VERSION(contigmem, 1); static struct cdevsw contigmem_ops = { .d_name = "contigmem", .d_version = D_VERSION, - .d_mmap = contigmem_mmap, + .d_flags = D_TRACKCLOSE, .d_mmap_single = contigmem_mmap_single, .d_open = contigmem_open, + .d_close = contigmem_close, }; static int @@ -124,6 +140,7 @@ contigmem_load() { char index_string[8], description[32]; int i, error = 0; + void *addr; if (contigmem_num_buffers > RTE_CONTIGMEM_MAX_NUM_BUFS) { printf("%d buffers requested is greater than %d allowed\n", @@ -141,18 +158,20 @@ contigmem_load() } for (i = 0; i < contigmem_num_buffers; i++) { - contigmem_buffers[i] = - contigmalloc(contigmem_buffer_size, M_CONTIGMEM, M_ZERO, 0, - BUS_SPACE_MAXADDR, contigmem_buffer_size, 0); - - if (contigmem_buffers[i] == NULL) { + addr = contigmalloc(contigmem_buffer_size, M_CONTIGMEM, M_ZERO, + 0, BUS_SPACE_MAXADDR, contigmem_buffer_size, 0); + if (addr == NULL) { printf("contigmalloc failed for buffer %d\n", i); error = ENOMEM; goto error; } - printf("%2u: virt=%p phys=%p\n", i, contigmem_buffers[i], - (void *)pmap_kextract((vm_offset_t)contigmem_buffers[i])); + printf("%2u: virt=%p phys=%p\n", i, addr, + (void *)pmap_kextract((vm_offset_t)addr)); + + mtx_init(&contigmem_buffers[i].mtx, "contigmem", NULL, MTX_DEF); + contigmem_buffers[i].addr = addr; + contigmem_buffers[i].refcnt = 0; snprintf(index_string, sizeof(index_string), "%d", i); snprintf(description, sizeof(description), @@ -170,10 +189,13 @@ contigmem_load() return 0; error: - for (i = 0; i < contigmem_num_buffers; i++) - if (contigmem_buffers[i] != NULL) - contigfree(contigmem_buffers[i], contigmem_buffer_size, - M_CONTIGMEM); + for (i = 0; i < contigmem_num_buffers; i++) { + if (contigmem_buffers[i].addr != NULL) + contigfree(contigmem_buffers[i].addr, + contigmem_buffer_size, M_CONTIGMEM); + if (mtx_initialized(&contigmem_buffers[i].mtx)) + mtx_destroy(&contigmem_buffers[i].mtx); + } return error; } @@ -183,16 +205,22 @@ contigmem_unload() { int i; + if (contigmem_refcnt > 0) + return EBUSY; + if (contigmem_cdev != NULL) destroy_dev(contigmem_cdev); if (contigmem_eh_tag != NULL) EVENTHANDLER_DEREGISTER(process_exit, contigmem_eh_tag); - for (i = 0; i < RTE_CONTIGMEM_MAX_NUM_BUFS; i++) - if (contigmem_buffers[i] != NULL) - contigfree(contigmem_buffers[i], contigmem_buffer_size, - M_CONTIGMEM); + for (i = 0; i < RTE_CONTIGMEM_MAX_NUM_BUFS; i++) { + if (contigmem_buffers[i].addr != NULL) + contigfree(contigmem_buffers[i].addr, + contigmem_buffer_size, M_CONTIGMEM); + if (mtx_initialized(&contigmem_buffers[i].mtx)) + mtx_destroy(&contigmem_buffers[i].mtx); + } return 0; } @@ -203,7 +231,7 @@ contigmem_physaddr(SYSCTL_HANDLER_ARGS) uint64_t physaddr; int index = (int)(uintptr_t)arg1; - physaddr = (uint64_t)vtophys(contigmem_buffers[index]); + physaddr = (uint64_t)vtophys(contigmem_buffers[index].addr); return sysctl_handle_64(oidp, &physaddr, 0, req); } @@ -211,22 +239,121 @@ static int contigmem_open(struct cdev *cdev, int fflags, int devtype, struct thread *td) { + + atomic_add_int(&contigmem_refcnt, 1); + + return 0; +} + +static int +contigmem_close(struct cdev *cdev, int fflags, int devtype, + struct thread *td) +{ + + atomic_subtract_int(&contigmem_refcnt, 1); + return 0; } static int -contigmem_mmap(struct cdev *cdev, vm_ooffset_t offset, vm_paddr_t *paddr, - int prot, vm_memattr_t *memattr) +contigmem_cdev_pager_ctor(void *handle, vm_ooffset_t size, vm_prot_t prot, + vm_ooffset_t foff, struct ucred *cred, u_short *color) { + struct contigmem_vm_handle *vmh = handle; + struct contigmem_buffer *buf; + + buf = &contigmem_buffers[vmh->buffer_index]; + + atomic_add_int(&contigmem_refcnt, 1); + + mtx_lock(&buf->mtx); + if (buf->refcnt == 0) + memset(buf->addr, 0, contigmem_buffer_size); + buf->refcnt++; + mtx_unlock(&buf->mtx); - *paddr = offset; return 0; } +static void +contigmem_cdev_pager_dtor(void *handle) +{ + struct contigmem_vm_handle *vmh = handle; + struct contigmem_buffer *buf; + + buf = &contigmem_buffers[vmh->buffer_index]; + + mtx_lock(&buf->mtx); + buf->refcnt--; + mtx_unlock(&buf->mtx); + + free(vmh, M_CONTIGMEM); + + atomic_subtract_int(&contigmem_refcnt, 1); +} + +static int +contigmem_cdev_pager_fault(vm_object_t object, vm_ooffset_t offset, int prot, + vm_page_t *mres) +{ + vm_paddr_t paddr; + vm_page_t m_paddr, page; + vm_memattr_t memattr, memattr1; + + memattr = object->memattr; + + VM_OBJECT_WUNLOCK(object); + + paddr = offset; + + m_paddr = vm_phys_paddr_to_vm_page(paddr); + if (m_paddr != NULL) { + memattr1 = pmap_page_get_memattr(m_paddr); + if (memattr1 != memattr) + memattr = memattr1; + } + + if (((*mres)->flags & PG_FICTITIOUS) != 0) { + /* + * If the passed in result page is a fake page, update it with + * the new physical address. + */ + page = *mres; + VM_OBJECT_WLOCK(object); + vm_page_updatefake(page, paddr, memattr); + } else { + vm_page_t mret; + /* + * Replace the passed in reqpage page with our own fake page and + * free up the original page. + */ + page = vm_page_getfake(paddr, memattr); + VM_OBJECT_WLOCK(object); + mret = vm_page_replace(page, object, (*mres)->pindex); + KASSERT(mret == *mres, + ("invalid page replacement, old=%p, ret=%p", *mres, mret)); + vm_page_lock(mret); + vm_page_free(mret); + vm_page_unlock(mret); + *mres = page; + } + + page->valid = VM_PAGE_BITS_ALL; + + return VM_PAGER_OK; +} + +static struct cdev_pager_ops contigmem_cdev_pager_ops = { + .cdev_pg_ctor = contigmem_cdev_pager_ctor, + .cdev_pg_dtor = contigmem_cdev_pager_dtor, + .cdev_pg_fault = contigmem_cdev_pager_fault, +}; + static int contigmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t size, struct vm_object **obj, int nprot) { + struct contigmem_vm_handle *vmh; uint64_t buffer_index; /* @@ -238,10 +365,17 @@ contigmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t size, if (buffer_index >= contigmem_num_buffers) return EINVAL; - memset(contigmem_buffers[buffer_index], 0, contigmem_buffer_size); - *offset = (vm_ooffset_t)vtophys(contigmem_buffers[buffer_index]); - *obj = vm_pager_allocate(OBJT_DEVICE, cdev, size, nprot, *offset, - curthread->td_ucred); + if (size > contigmem_buffer_size) + return EINVAL; + + vmh = malloc(sizeof(*vmh), M_CONTIGMEM, M_NOWAIT | M_ZERO); + if (vmh == NULL) + return ENOMEM; + vmh->buffer_index = buffer_index; + + *offset = (vm_ooffset_t)vtophys(contigmem_buffers[buffer_index].addr); + *obj = cdev_pager_allocate(vmh, OBJT_DEVICE, &contigmem_cdev_pager_ops, + size, nprot, *offset, curthread->td_ucred); return 0; } -- 2.13.0 ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [dpdk-dev] [PATCH v3 0/2] Various fixes for contigmem 2017-06-04 5:53 ` [dpdk-dev] [PATCH v3 0/2] Various fixes for contigmem Tiwei Bie 2017-06-04 5:53 ` [dpdk-dev] [PATCH v3 1/2] contigmem: free the allocated memory when error occurs Tiwei Bie 2017-06-04 5:53 ` [dpdk-dev] [PATCH v3 2/2] contigmem: don't zero the pages during each mmap Tiwei Bie @ 2017-07-03 23:33 ` Thomas Monjalon 2 siblings, 0 replies; 13+ messages in thread From: Thomas Monjalon @ 2017-07-03 23:33 UTC (permalink / raw) To: Tiwei Bie; +Cc: dev, bruce.richardson 04/06/2017 07:53, Tiwei Bie: > The vm_page_replace_checked() was introduced in FreeBSD 11, so the > build is broken on FreeBSD 10. The fix is to use vm_page_replace() > directly and do the check in caller. > > --- > > v2: destroy the initialized mtx before failing or unloading > v3: fix build on FreeBSD 10, refine comments > > Tiwei Bie (2): > contigmem: free the allocated memory when error occurs > contigmem: don't zero the pages during each mmap Applied, thanks ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2017-07-03 23:33 UTC | newest] Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2017-05-09 8:47 [dpdk-dev] [PATCH 0/2] Various fixes for contigmem Tiwei Bie 2017-05-09 8:47 ` [dpdk-dev] [PATCH 1/2] contigmem: free the allocated memory when error occurs Tiwei Bie 2017-05-09 8:47 ` [dpdk-dev] [PATCH 2/2] contigmem: don't zero the pages during each mmap Tiwei Bie 2017-05-10 14:05 ` [dpdk-dev] [PATCH 0/2] Various fixes for contigmem Richardson, Bruce 2017-05-11 1:03 ` Tiwei Bie 2017-05-22 9:03 ` [dpdk-dev] [PATCH v2 " Tiwei Bie 2017-05-22 9:03 ` [dpdk-dev] [PATCH v2 1/2] contigmem: free the allocated memory when error occurs Tiwei Bie 2017-05-22 9:03 ` [dpdk-dev] [PATCH v2 2/2] contigmem: don't zero the pages during each mmap Tiwei Bie 2017-05-22 10:15 ` [dpdk-dev] [dpdk-stable] " Shahaf Shuler 2017-06-04 5:53 ` [dpdk-dev] [PATCH v3 0/2] Various fixes for contigmem Tiwei Bie 2017-06-04 5:53 ` [dpdk-dev] [PATCH v3 1/2] contigmem: free the allocated memory when error occurs Tiwei Bie 2017-06-04 5:53 ` [dpdk-dev] [PATCH v3 2/2] contigmem: don't zero the pages during each mmap Tiwei Bie 2017-07-03 23:33 ` [dpdk-dev] [PATCH v3 0/2] Various fixes for contigmem Thomas Monjalon
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).