Roland, can you review this?
----- From: Steve Wise <[EMAIL PROTECTED]> Currently iw_cxgb3 uses the physical address as the key/offset to return to the user process for maping kernel memory into userspace. The user process then calls mmap() using this key as the offset. Because the physical address is 64 bits, this introduces a problem with 32-bit userspace, which might not be able to pass an arbitrary 64-bit address back into the kernel (since mmap2() is limited to a 32-bit number of pages for the offset, which limits it to 44-bit addresses). Change the mmap logic to use a u32 counter as the offset for mapping. Signed-off-by: Steve Wise <[EMAIL PROTECTED]> --- drivers/infiniband/hw/cxgb3/iwch_provider.c | 66 +++++++++++++++++---------- drivers/infiniband/hw/cxgb3/iwch_provider.h | 13 +++-- drivers/infiniband/hw/cxgb3/iwch_user.h | 6 +- 3 files changed, 52 insertions(+), 33 deletions(-) diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c index d02cd72..b2c88d6 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.c +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.c @@ -115,7 +115,7 @@ static struct ib_ucontext *iwch_alloc_uc struct iwch_dev *rhp = to_iwch_dev(ibdev); PDBG("%s ibdev %p\n", __FUNCTION__, ibdev); - context = kmalloc(sizeof(*context), GFP_KERNEL); + context = kzalloc(sizeof(*context), GFP_KERNEL); if (!context) return ERR_PTR(-ENOMEM); cxio_init_ucontext(&rhp->rdev, &context->uctx); @@ -141,13 +141,14 @@ static int iwch_destroy_cq(struct ib_cq } static struct ib_cq *iwch_create_cq(struct ib_device *ibdev, int entries, - struct ib_ucontext *context, + struct ib_ucontext *ib_context, struct ib_udata *udata) { struct iwch_dev *rhp; struct iwch_cq *chp; struct iwch_create_cq_resp uresp; struct iwch_create_cq_req ureq; + struct iwch_ucontext *ucontext = NULL; PDBG("%s ib_dev %p entries %d\n", __FUNCTION__, ibdev, entries); rhp = to_iwch_dev(ibdev); @@ -155,12 +156,15 @@ static struct ib_cq *iwch_create_cq(stru if (!chp) return ERR_PTR(-ENOMEM); - if (context && !t3a_device(rhp)) { - if (ib_copy_from_udata(&ureq, udata, sizeof (ureq))) { - kfree(chp); - return ERR_PTR(-EFAULT); + if (ib_context) { + ucontext = to_iwch_ucontext(ib_context); + if (!t3a_device(rhp)) { + if (ib_copy_from_udata(&ureq, udata, sizeof (ureq))) { + kfree(chp); + return ERR_PTR(-EFAULT); + } + chp->user_rptr_addr = (u32 __user *)(unsigned long)ureq.user_rptr_addr; } - chp->user_rptr_addr = (u32 __user *)(unsigned long)ureq.user_rptr_addr; } if (t3a_device(rhp)) { @@ -190,7 +194,7 @@ static struct ib_cq *iwch_create_cq(stru init_waitqueue_head(&chp->wait); insert_handle(rhp, &rhp->cqidr, chp, chp->cq.cqid); - if (context) { + if (ucontext) { struct iwch_mm_entry *mm; mm = kmalloc(sizeof *mm, GFP_KERNEL); @@ -200,16 +204,20 @@ static struct ib_cq *iwch_create_cq(stru } uresp.cqid = chp->cq.cqid; uresp.size_log2 = chp->cq.size_log2; - uresp.physaddr = virt_to_phys(chp->cq.queue); + spin_lock(&ucontext->mmap_lock); + uresp.key = ucontext->key; + ucontext->key += PAGE_SIZE; + spin_unlock(&ucontext->mmap_lock); if (ib_copy_to_udata(udata, &uresp, sizeof (uresp))) { kfree(mm); iwch_destroy_cq(&chp->ibcq); return ERR_PTR(-EFAULT); } - mm->addr = uresp.physaddr; + mm->key = uresp.key; + mm->addr = virt_to_phys(chp->cq.queue); mm->len = PAGE_ALIGN((1UL << uresp.size_log2) * sizeof (struct t3_cqe)); - insert_mmap(to_iwch_ucontext(context), mm); + insert_mmap(ucontext, mm); } PDBG("created cqid 0x%0x chp %p size 0x%0x, dma_addr 0x%0llx\n", chp->cq.cqid, chp, (1 << chp->cq.size_log2), @@ -316,14 +324,14 @@ static int iwch_arm_cq(struct ib_cq *ibc static int iwch_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) { int len = vma->vm_end - vma->vm_start; - u64 pgaddr = vma->vm_pgoff << PAGE_SHIFT; + u32 key = vma->vm_pgoff << PAGE_SHIFT; struct cxio_rdev *rdev_p; int ret = 0; struct iwch_mm_entry *mm; struct iwch_ucontext *ucontext; - PDBG("%s off 0x%lx addr 0x%llx len %d\n", __FUNCTION__, vma->vm_pgoff, - pgaddr, len); + PDBG("%s pgoff 0x%lx key 0x%x len %d\n", __FUNCTION__, vma->vm_pgoff, + key, len); if (vma->vm_start & (PAGE_SIZE-1)) { return -EINVAL; @@ -332,13 +340,13 @@ static int iwch_mmap(struct ib_ucontext rdev_p = &(to_iwch_dev(context->device)->rdev); ucontext = to_iwch_ucontext(context); - mm = remove_mmap(ucontext, pgaddr, len); + mm = remove_mmap(ucontext, key, len); if (!mm) return -EINVAL; kfree(mm); - if ((pgaddr >= rdev_p->rnic_info.udbell_physbase) && - (pgaddr < (rdev_p->rnic_info.udbell_physbase + + if ((mm->addr >= rdev_p->rnic_info.udbell_physbase) && + (mm->addr < (rdev_p->rnic_info.udbell_physbase + rdev_p->rnic_info.udbell_len))) { /* @@ -351,15 +359,17 @@ static int iwch_mmap(struct ib_ucontext vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); vma->vm_flags |= VM_DONTCOPY | VM_DONTEXPAND; vma->vm_flags &= ~VM_MAYREAD; - ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, - len, vma->vm_page_prot); + ret = io_remap_pfn_range(vma, vma->vm_start, + mm->addr >> PAGE_SHIFT, + len, vma->vm_page_prot); } else { /* * Map WQ or CQ contig dma memory... */ - ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, - len, vma->vm_page_prot); + ret = remap_pfn_range(vma, vma->vm_start, + mm->addr >> PAGE_SHIFT, + len, vma->vm_page_prot); } return ret; @@ -853,18 +863,24 @@ static struct ib_qp *iwch_create_qp(stru uresp.size_log2 = qhp->wq.size_log2; uresp.sq_size_log2 = qhp->wq.sq_size_log2; uresp.rq_size_log2 = qhp->wq.rq_size_log2; - uresp.physaddr = virt_to_phys(qhp->wq.queue); - uresp.doorbell = qhp->wq.udb; + spin_lock(&ucontext->mmap_lock); + uresp.key = ucontext->key; + ucontext->key += PAGE_SIZE; + uresp.db_key = ucontext->key; + ucontext->key += PAGE_SIZE; + spin_unlock(&ucontext->mmap_lock); if (ib_copy_to_udata(udata, &uresp, sizeof (uresp))) { kfree(mm1); kfree(mm2); iwch_destroy_qp(&qhp->ibqp); return ERR_PTR(-EFAULT); } - mm1->addr = uresp.physaddr; + mm1->key = uresp.key; + mm1->addr = virt_to_phys(qhp->wq.queue); mm1->len = PAGE_ALIGN(wqsize * sizeof (union t3_wr)); insert_mmap(ucontext, mm1); - mm2->addr = uresp.doorbell & PAGE_MASK; + mm2->key = uresp.db_key; + mm2->addr = qhp->wq.udb & PAGE_MASK; mm2->len = PAGE_SIZE; insert_mmap(ucontext, mm2); } diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.h b/drivers/infiniband/hw/cxgb3/iwch_provider.h index b2eb29e..463e746 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_provider.h +++ b/drivers/infiniband/hw/cxgb3/iwch_provider.h @@ -184,6 +184,7 @@ struct ib_qp *iwch_get_qp(struct ib_devi struct iwch_ucontext { struct ib_ucontext ibucontext; struct cxio_ucontext uctx; + u32 key; spinlock_t mmap_lock; struct list_head mmaps; }; @@ -196,11 +197,12 @@ static inline struct iwch_ucontext *to_i struct iwch_mm_entry { struct list_head entry; u64 addr; + u32 key; unsigned len; }; static inline struct iwch_mm_entry *remove_mmap(struct iwch_ucontext *ucontext, - u64 addr, unsigned len) + u32 key, unsigned len) { struct list_head *pos, *nxt; struct iwch_mm_entry *mm; @@ -209,11 +211,11 @@ static inline struct iwch_mm_entry *remo list_for_each_safe(pos, nxt, &ucontext->mmaps) { mm = list_entry(pos, struct iwch_mm_entry, entry); - if (mm->addr == addr && mm->len == len) { + if (mm->key == key && mm->len == len) { list_del_init(&mm->entry); spin_unlock(&ucontext->mmap_lock); - PDBG("%s addr 0x%llx len %d\n", __FUNCTION__, mm->addr, - mm->len); + PDBG("%s addr 0x%llx key 0x%x len %d\n", + __FUNCTION__, mm->addr, mm->key, mm->len); return mm; } } @@ -225,7 +227,8 @@ static inline void insert_mmap(struct iw struct iwch_mm_entry *mm) { spin_lock(&ucontext->mmap_lock); - PDBG("%s addr 0x%llx len %d\n", __FUNCTION__, mm->addr, mm->len); + PDBG("%s addr 0x%llx key 0x%x len %d\n", __FUNCTION__, + mm->addr, mm->key, mm->len); list_add_tail(&mm->entry, &ucontext->mmaps); spin_unlock(&ucontext->mmap_lock); } diff --git a/drivers/infiniband/hw/cxgb3/iwch_user.h b/drivers/infiniband/hw/cxgb3/iwch_user.h index 14e1517..c4e7fbe 100644 --- a/drivers/infiniband/hw/cxgb3/iwch_user.h +++ b/drivers/infiniband/hw/cxgb3/iwch_user.h @@ -47,14 +47,14 @@ struct iwch_create_cq_req { }; struct iwch_create_cq_resp { - __u64 physaddr; + __u64 key; __u32 cqid; __u32 size_log2; }; struct iwch_create_qp_resp { - __u64 physaddr; - __u64 doorbell; + __u64 key; + __u64 db_key; __u32 qpid; __u32 size_log2; __u32 sq_size_log2; _______________________________________________ openib-general mailing list openib-general@openib.org http://openib.org/mailman/listinfo/openib-general To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general