Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

RDMA/mlx4: Do not map the core_clock page to user space unless enabled

Currently when mlx4 maps the hca_core_clock page to the user space there
are read-modifiable registers, one of which is semaphore, on this page as
well as the clock counter. If user reads the wrong offset, it can modify
the semaphore and hang the device.

Do not map the hca_core_clock page to the user space unless the device has
been put in a backwards compatibility mode to support this feature.

After this patch, mlx4 core_clock won't be mapped to user space on the
majority of existing devices and the uverbs device time feature in
ibv_query_rt_values_ex() will be disabled.

Fixes: 52033cfb5aab ("IB/mlx4: Add mmap call to map the hardware clock")
Link: https://lore.kernel.org/r/9632304e0d6790af84b3b706d8c18732bc0d5e27.1622726305.git.leonro@nvidia.com
Signed-off-by: Shay Drory <shayd@nvidia.com>
Signed-off-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>

authored by

Shay Drory and committed by
Jason Gunthorpe
404e5a12 a0ffb4c1

+12 -4
+1 -4
drivers/infiniband/hw/mlx4/main.c
··· 581 581 props->cq_caps.max_cq_moderation_count = MLX4_MAX_CQ_COUNT; 582 582 props->cq_caps.max_cq_moderation_period = MLX4_MAX_CQ_PERIOD; 583 583 584 - if (!mlx4_is_slave(dev->dev)) 585 - err = mlx4_get_internal_clock_params(dev->dev, &clock_params); 586 - 587 584 if (uhw->outlen >= resp.response_length + sizeof(resp.hca_core_clock_offset)) { 588 585 resp.response_length += sizeof(resp.hca_core_clock_offset); 589 - if (!err && !mlx4_is_slave(dev->dev)) { 586 + if (!mlx4_get_internal_clock_params(dev->dev, &clock_params)) { 590 587 resp.comp_mask |= MLX4_IB_QUERY_DEV_RESP_MASK_CORE_CLOCK_OFFSET; 591 588 resp.hca_core_clock_offset = clock_params.offset % PAGE_SIZE; 592 589 }
+3
drivers/net/ethernet/mellanox/mlx4/fw.c
··· 823 823 #define QUERY_DEV_CAP_MAD_DEMUX_OFFSET 0xb0 824 824 #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET 0xa8 825 825 #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET 0xac 826 + #define QUERY_DEV_CAP_MAP_CLOCK_TO_USER 0xc1 826 827 #define QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET 0xcc 827 828 #define QUERY_DEV_CAP_QP_RATE_LIMIT_MAX_OFFSET 0xd0 828 829 #define QUERY_DEV_CAP_QP_RATE_LIMIT_MIN_OFFSET 0xd2 ··· 842 841 843 842 if (mlx4_is_mfunc(dev)) 844 843 disable_unsupported_roce_caps(outbox); 844 + MLX4_GET(field, outbox, QUERY_DEV_CAP_MAP_CLOCK_TO_USER); 845 + dev_cap->map_clock_to_user = field & 0x80; 845 846 MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_QP_OFFSET); 846 847 dev_cap->reserved_qps = 1 << (field & 0xf); 847 848 MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_OFFSET);
+1
drivers/net/ethernet/mellanox/mlx4/fw.h
··· 131 131 u32 health_buffer_addrs; 132 132 struct mlx4_port_cap port_cap[MLX4_MAX_PORTS + 1]; 133 133 bool wol_port[MLX4_MAX_PORTS + 1]; 134 + bool map_clock_to_user; 134 135 }; 135 136 136 137 struct mlx4_func_cap {
+6
drivers/net/ethernet/mellanox/mlx4/main.c
··· 498 498 } 499 499 } 500 500 501 + dev->caps.map_clock_to_user = dev_cap->map_clock_to_user; 501 502 dev->caps.uar_page_size = PAGE_SIZE; 502 503 dev->caps.num_uars = dev_cap->uar_size / PAGE_SIZE; 503 504 dev->caps.local_ca_ack_delay = dev_cap->local_ca_ack_delay; ··· 1948 1947 1949 1948 if (mlx4_is_slave(dev)) 1950 1949 return -EOPNOTSUPP; 1950 + 1951 + if (!dev->caps.map_clock_to_user) { 1952 + mlx4_dbg(dev, "Map clock to user is not supported.\n"); 1953 + return -EOPNOTSUPP; 1954 + } 1951 1955 1952 1956 if (!params) 1953 1957 return -EINVAL;
+1
include/linux/mlx4/device.h
··· 630 630 bool wol_port[MLX4_MAX_PORTS + 1]; 631 631 struct mlx4_rate_limit_caps rl_caps; 632 632 u32 health_buffer_addrs; 633 + bool map_clock_to_user; 633 634 }; 634 635 635 636 struct mlx4_buf_list {