[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 11:30:10 PST 2007
Roland, can you review this?
-----
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 | 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;
More information about the general
mailing list