mirror of https://gitee.com/openkylin/linux.git
mlx4_core: Fix integer overflows so 8TBs of memory registration works
This patch adds on the fixes done in commits89dd86db78
("mlx4_core: Allow large mlx4_buddy bitmaps") and3de819e6b6
("mlx4_core: Fix integer overflow issues around MTT table") so that memory registration of up to 8TB (log_num_mtt=31) finally works. It fixes integer overflows in a few mlx4_table_yyy routines in icm.c by using a u64 intermediate variable, and int/uint issues that caused table indexes to become nagive by setting some variables to be u32 instead of int. These problems cause crashes when a user attempted to register > 512GB of RAM. Signed-off-by: Yishai Hadas <yishaih@mellanox.com> Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
This commit is contained in:
parent
fea7a08acb
commit
dd03e73481
|
@ -227,9 +227,10 @@ int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev)
|
||||||
MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
|
MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj)
|
int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj)
|
||||||
{
|
{
|
||||||
int i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size);
|
u32 i = (obj & (table->num_obj - 1)) /
|
||||||
|
(MLX4_TABLE_CHUNK_SIZE / table->obj_size);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
mutex_lock(&table->mutex);
|
mutex_lock(&table->mutex);
|
||||||
|
@ -262,16 +263,18 @@ int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj)
|
void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj)
|
||||||
{
|
{
|
||||||
int i;
|
u32 i;
|
||||||
|
u64 offset;
|
||||||
|
|
||||||
i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size);
|
i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size);
|
||||||
|
|
||||||
mutex_lock(&table->mutex);
|
mutex_lock(&table->mutex);
|
||||||
|
|
||||||
if (--table->icm[i]->refcount == 0) {
|
if (--table->icm[i]->refcount == 0) {
|
||||||
mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE,
|
offset = (u64) i * MLX4_TABLE_CHUNK_SIZE;
|
||||||
|
mlx4_UNMAP_ICM(dev, table->virt + offset,
|
||||||
MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE);
|
MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE);
|
||||||
mlx4_free_icm(dev, table->icm[i], table->coherent);
|
mlx4_free_icm(dev, table->icm[i], table->coherent);
|
||||||
table->icm[i] = NULL;
|
table->icm[i] = NULL;
|
||||||
|
@ -280,9 +283,11 @@ void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj)
|
||||||
mutex_unlock(&table->mutex);
|
mutex_unlock(&table->mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle)
|
void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj,
|
||||||
|
dma_addr_t *dma_handle)
|
||||||
{
|
{
|
||||||
int idx, offset, dma_offset, i;
|
int offset, dma_offset, i;
|
||||||
|
u64 idx;
|
||||||
struct mlx4_icm_chunk *chunk;
|
struct mlx4_icm_chunk *chunk;
|
||||||
struct mlx4_icm *icm;
|
struct mlx4_icm *icm;
|
||||||
struct page *page = NULL;
|
struct page *page = NULL;
|
||||||
|
@ -292,7 +297,7 @@ void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_han
|
||||||
|
|
||||||
mutex_lock(&table->mutex);
|
mutex_lock(&table->mutex);
|
||||||
|
|
||||||
idx = (obj & (table->num_obj - 1)) * table->obj_size;
|
idx = (u64) (obj & (table->num_obj - 1)) * table->obj_size;
|
||||||
icm = table->icm[idx / MLX4_TABLE_CHUNK_SIZE];
|
icm = table->icm[idx / MLX4_TABLE_CHUNK_SIZE];
|
||||||
dma_offset = offset = idx % MLX4_TABLE_CHUNK_SIZE;
|
dma_offset = offset = idx % MLX4_TABLE_CHUNK_SIZE;
|
||||||
|
|
||||||
|
@ -326,10 +331,11 @@ void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_han
|
||||||
}
|
}
|
||||||
|
|
||||||
int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
|
int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
|
||||||
int start, int end)
|
u32 start, u32 end)
|
||||||
{
|
{
|
||||||
int inc = MLX4_TABLE_CHUNK_SIZE / table->obj_size;
|
int inc = MLX4_TABLE_CHUNK_SIZE / table->obj_size;
|
||||||
int i, err;
|
int err;
|
||||||
|
u32 i;
|
||||||
|
|
||||||
for (i = start; i <= end; i += inc) {
|
for (i = start; i <= end; i += inc) {
|
||||||
err = mlx4_table_get(dev, table, i);
|
err = mlx4_table_get(dev, table, i);
|
||||||
|
@ -349,9 +355,9 @@ int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
|
||||||
}
|
}
|
||||||
|
|
||||||
void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
|
void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
|
||||||
int start, int end)
|
u32 start, u32 end)
|
||||||
{
|
{
|
||||||
int i;
|
u32 i;
|
||||||
|
|
||||||
for (i = start; i <= end; i += MLX4_TABLE_CHUNK_SIZE / table->obj_size)
|
for (i = start; i <= end; i += MLX4_TABLE_CHUNK_SIZE / table->obj_size)
|
||||||
mlx4_table_put(dev, table, i);
|
mlx4_table_put(dev, table, i);
|
||||||
|
|
|
@ -71,17 +71,17 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
|
||||||
gfp_t gfp_mask, int coherent);
|
gfp_t gfp_mask, int coherent);
|
||||||
void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent);
|
void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent);
|
||||||
|
|
||||||
int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj);
|
int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj);
|
||||||
void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj);
|
void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj);
|
||||||
int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
|
int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
|
||||||
int start, int end);
|
u32 start, u32 end);
|
||||||
void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
|
void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
|
||||||
int start, int end);
|
u32 start, u32 end);
|
||||||
int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,
|
int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,
|
||||||
u64 virt, int obj_size, u32 nobj, int reserved,
|
u64 virt, int obj_size, u32 nobj, int reserved,
|
||||||
int use_lowmem, int use_coherent);
|
int use_lowmem, int use_coherent);
|
||||||
void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table);
|
void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table);
|
||||||
void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle);
|
void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, dma_addr_t *dma_handle);
|
||||||
|
|
||||||
static inline void mlx4_icm_first(struct mlx4_icm *icm,
|
static inline void mlx4_icm_first(struct mlx4_icm *icm,
|
||||||
struct mlx4_icm_iter *iter)
|
struct mlx4_icm_iter *iter)
|
||||||
|
|
Loading…
Reference in New Issue