Skip to content

Commit

Permalink
IB/{rxe,core,rdmavt}: Fix kernel crash for reg MR
Browse files Browse the repository at this point in the history
This patch fixes below kernel crash on memory registration for rxe
and other transport drivers which has dma_ops extension.

IB/core invokes ib_map_sg_attrs() in generic manner with dma attributes
which is used by mlx5 and mthca adapters.  However in doing so it
ignored honoring dma_ops extension of software based transports for
sg map/unmap operation.  This results in calling dma_map_sg_attrs of
hardware virtual device resulting in crash for null reference.

We extend the core to support sg_map/unmap_attrs and transport drivers
to implement those dma_ops callback functions.

Verified usign perftest applications.

BUG: unable to handle kernel NULL pointer dereference at           (null)
IP: [<ffffffff81032a75>] check_addr+0x35/0x60
...
Call Trace:
 [<ffffffff81032b39>] ? nommu_map_sg+0x99/0xd0
 [<ffffffffa02b31c6>] ib_umem_get+0x3d6/0x470 [ib_core]
 [<ffffffffa01cc329>] rxe_mem_init_user+0x49/0x270 [rdma_rxe]
 [<ffffffffa01c793a>] ? rxe_add_index+0xca/0x100 [rdma_rxe]
 [<ffffffffa01c995f>] rxe_reg_user_mr+0x9f/0x130 [rdma_rxe]
 [<ffffffffa00419fe>] ib_uverbs_reg_mr+0x14e/0x2c0 [ib_uverbs]
 [<ffffffffa003d3ab>] ib_uverbs_write+0x15b/0x3b0 [ib_uverbs]
 [<ffffffff811e92a6>] ? mem_cgroup_commit_charge+0x76/0xe0
 [<ffffffff811af0a9>] ? page_add_new_anon_rmap+0x89/0xc0
 [<ffffffff8117e6c9>] ? lru_cache_add_active_or_unevictable+0x39/0xc0
 [<ffffffff811f0da8>] __vfs_write+0x28/0x120
 [<ffffffff811f1239>] ? rw_verify_area+0x49/0xb0
 [<ffffffff811f1492>] vfs_write+0xb2/0x1b0
 [<ffffffff811f27d6>] SyS_write+0x46/0xa0
 [<ffffffff814f7d32>] entry_SYSCALL_64_fastpath+0x1a/0xa4

Signed-off-by: Parav Pandit <pandit.parav@gmail.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
  • Loading branch information
Parav Pandit authored and Doug Ledford committed Oct 6, 2016
1 parent ffae955 commit d970365
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 3 deletions.
17 changes: 17 additions & 0 deletions drivers/infiniband/sw/rdmavt/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,21 @@ static void rvt_unmap_sg(struct ib_device *dev,
/* This is a stub, nothing to be done here */
}

static int rvt_map_sg_attrs(struct ib_device *dev, struct scatterlist *sgl,
int nents, enum dma_data_direction direction,
unsigned long attrs)
{
return rvt_map_sg(dev, sgl, nents, direction);
}

static void rvt_unmap_sg_attrs(struct ib_device *dev,
struct scatterlist *sg, int nents,
enum dma_data_direction direction,
unsigned long attrs)
{
return rvt_unmap_sg(dev, sg, nents, direction);
}

static void rvt_sync_single_for_cpu(struct ib_device *dev, u64 addr,
size_t size, enum dma_data_direction dir)
{
Expand Down Expand Up @@ -177,6 +192,8 @@ struct ib_dma_mapping_ops rvt_default_dma_mapping_ops = {
.unmap_page = rvt_dma_unmap_page,
.map_sg = rvt_map_sg,
.unmap_sg = rvt_unmap_sg,
.map_sg_attrs = rvt_map_sg_attrs,
.unmap_sg_attrs = rvt_unmap_sg_attrs,
.sync_single_for_cpu = rvt_sync_single_for_cpu,
.sync_single_for_device = rvt_sync_single_for_device,
.alloc_coherent = rvt_dma_alloc_coherent,
Expand Down
17 changes: 17 additions & 0 deletions drivers/infiniband/sw/rxe/rxe_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,21 @@ static void rxe_unmap_sg(struct ib_device *dev,
WARN_ON(!valid_dma_direction(direction));
}

static int rxe_map_sg_attrs(struct ib_device *dev, struct scatterlist *sgl,
int nents, enum dma_data_direction direction,
unsigned long attrs)
{
return rxe_map_sg(dev, sgl, nents, direction);
}

static void rxe_unmap_sg_attrs(struct ib_device *dev,
struct scatterlist *sg, int nents,
enum dma_data_direction direction,
unsigned long attrs)
{
rxe_unmap_sg(dev, sg, nents, direction);
}

static void rxe_sync_single_for_cpu(struct ib_device *dev,
u64 addr,
size_t size, enum dma_data_direction dir)
Expand Down Expand Up @@ -159,6 +174,8 @@ struct ib_dma_mapping_ops rxe_dma_mapping_ops = {
.unmap_page = rxe_dma_unmap_page,
.map_sg = rxe_map_sg,
.unmap_sg = rxe_unmap_sg,
.map_sg_attrs = rxe_map_sg_attrs,
.unmap_sg_attrs = rxe_unmap_sg_attrs,
.sync_single_for_cpu = rxe_sync_single_for_cpu,
.sync_single_for_device = rxe_sync_single_for_device,
.alloc_coherent = rxe_dma_alloc_coherent,
Expand Down
23 changes: 20 additions & 3 deletions include/rdma/ib_verbs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1739,6 +1739,14 @@ struct ib_dma_mapping_ops {
void (*unmap_sg)(struct ib_device *dev,
struct scatterlist *sg, int nents,
enum dma_data_direction direction);
int (*map_sg_attrs)(struct ib_device *dev,
struct scatterlist *sg, int nents,
enum dma_data_direction direction,
unsigned long attrs);
void (*unmap_sg_attrs)(struct ib_device *dev,
struct scatterlist *sg, int nents,
enum dma_data_direction direction,
unsigned long attrs);
void (*sync_single_for_cpu)(struct ib_device *dev,
u64 dma_handle,
size_t size,
Expand Down Expand Up @@ -3000,16 +3008,25 @@ static inline int ib_dma_map_sg_attrs(struct ib_device *dev,
enum dma_data_direction direction,
unsigned long dma_attrs)
{
return dma_map_sg_attrs(dev->dma_device, sg, nents, direction,
dma_attrs);
if (dev->dma_ops)
return dev->dma_ops->map_sg_attrs(dev, sg, nents, direction,
dma_attrs);
else
return dma_map_sg_attrs(dev->dma_device, sg, nents, direction,
dma_attrs);
}

static inline void ib_dma_unmap_sg_attrs(struct ib_device *dev,
struct scatterlist *sg, int nents,
enum dma_data_direction direction,
unsigned long dma_attrs)
{
dma_unmap_sg_attrs(dev->dma_device, sg, nents, direction, dma_attrs);
if (dev->dma_ops)
return dev->dma_ops->unmap_sg_attrs(dev, sg, nents, direction,
dma_attrs);
else
dma_unmap_sg_attrs(dev->dma_device, sg, nents, direction,
dma_attrs);
}
/**
* ib_sg_dma_address - Return the DMA address from a scatter/gather entry
Expand Down

0 comments on commit d970365

Please sign in to comment.