[openib-general] [PATCH][RFC] iw_cxgb3/2.6.21 - Don't use the physical address for mapping memory into userspace.

Steve Wise swise at opengridcomputing.com
Mon Feb 12 13:15:53 PST 2007


On Mon, 2007-02-12 at 12:23 -0800, Roland Dreier wrote:
> Actually, that patch doesn't apply because of the "%llx" warning fixes
> I pushed out.  And git-apply also complains about trailing
> whitespace.  Can you resend a version that applies to the my
> for-2.6.21 branch?
> 
> Thanks

Here it is...


Don't use the physical address for mapping memory into userspace.

From: Steve Wise <swise at opengridcomputing.com>

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 <swise at opengridcomputing.com>
---

 drivers/infiniband/hw/cxgb3/iwch_provider.c |   66 +++++++++++++++++----------
 drivers/infiniband/hw/cxgb3/iwch_provider.h |   14 +++---
 drivers/infiniband/hw/cxgb3/iwch_user.h     |    6 +-
 3 files changed, 52 insertions(+), 34 deletions(-)

diff --git a/drivers/infiniband/hw/cxgb3/iwch_provider.c b/drivers/infiniband/hw/cxgb3/iwch_provider.c
index 549de0a..2e05e94 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,
-	     (unsigned long long) 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 5680d82..61e3278 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__,
-			     (unsigned long long) mm->addr, mm->len);
+			PDBG("%s key 0x%x addr 0x%llx len %d\n", __FUNCTION__,
+			     key, (unsigned long long) mm->addr, mm->len);
 			return mm;
 		}
 	}
@@ -225,8 +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__,
-	     (unsigned long long) mm->addr, mm->len);
+	PDBG("%s key 0x%x addr 0x%llx len %d\n", __FUNCTION__,
+	     mm->key, (unsigned long long) mm->addr, 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;






More information about the general mailing list