From c8301cbb0fa25d03c1b6b2d056497d5a1580a8b4 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Wed, 16 Jun 2021 15:02:02 +0200 Subject: [PATCH] mlx4: Map core_clock page to user space only when allowed Currently when we map the hca_core_clock page to the user space, there are vulnerable registers, one of which is semaphore, on this page as well. If user read the wrong offset, it can modify the above semaphore and hang the device. Hence, mapping the hca_core_clock page to the user space only when user required it specifically. After this patch, mlx4 core_clock won't be mapped to user space by default. Oppose to current state, where mlx4 core_clock is always mapped to user space. MFC after: 1 week Reviewed by: kib Sponsored by: Mellanox Technologies // NVIDIA Networking --- sys/dev/mlx4/device.h | 1 + sys/dev/mlx4/mlx4_core/fw.h | 1 + sys/dev/mlx4/mlx4_core/mlx4_fw.c | 3 +++ sys/dev/mlx4/mlx4_core/mlx4_main.c | 6 ++++++ sys/dev/mlx4/mlx4_ib/mlx4_ib_main.c | 5 +---- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/sys/dev/mlx4/device.h b/sys/dev/mlx4/device.h index 0af8fce5e634..ce934838253f 100644 --- a/sys/dev/mlx4/device.h +++ b/sys/dev/mlx4/device.h @@ -624,6 +624,7 @@ struct mlx4_caps { u32 dmfs_high_rate_qpn_range; u32 vf_caps; struct mlx4_rate_limit_caps rl_caps; + bool map_clock_to_user; }; struct mlx4_buf_list { diff --git a/sys/dev/mlx4/mlx4_core/fw.h b/sys/dev/mlx4/mlx4_core/fw.h index c4c4883b4d06..48ba434e6078 100644 --- a/sys/dev/mlx4/mlx4_core/fw.h +++ b/sys/dev/mlx4/mlx4_core/fw.h @@ -129,6 +129,7 @@ struct mlx4_dev_cap { u32 dmfs_high_rate_qpn_range; struct mlx4_rate_limit_caps rl_caps; struct mlx4_port_cap port_cap[MLX4_MAX_PORTS + 1]; + bool map_clock_to_user; }; struct mlx4_func_cap { diff --git a/sys/dev/mlx4/mlx4_core/mlx4_fw.c b/sys/dev/mlx4/mlx4_core/mlx4_fw.c index 0ac45e1297b9..68aa7e76c79d 100644 --- a/sys/dev/mlx4/mlx4_core/mlx4_fw.c +++ b/sys/dev/mlx4/mlx4_core/mlx4_fw.c @@ -820,6 +820,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) #define QUERY_DEV_CAP_MAD_DEMUX_OFFSET 0xb0 #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET 0xa8 #define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET 0xac +#define QUERY_DEV_CAP_MAP_CLOCK_TO_USER 0xc1 #define QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET 0xcc #define QUERY_DEV_CAP_QP_RATE_LIMIT_MAX_OFFSET 0xd0 #define QUERY_DEV_CAP_QP_RATE_LIMIT_MIN_OFFSET 0xd2 @@ -838,6 +839,8 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) if (mlx4_is_mfunc(dev)) disable_unsupported_roce_caps(outbox); + MLX4_GET(field, outbox, QUERY_DEV_CAP_MAP_CLOCK_TO_USER); + dev_cap->map_clock_to_user = field & 0x80; MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_QP_OFFSET); dev_cap->reserved_qps = 1 << (field & 0xf); MLX4_GET(field, outbox, QUERY_DEV_CAP_MAX_QP_OFFSET); diff --git a/sys/dev/mlx4/mlx4_core/mlx4_main.c b/sys/dev/mlx4/mlx4_core/mlx4_main.c index 48cc2fc7d3f6..ca63d1d12ba6 100644 --- a/sys/dev/mlx4/mlx4_core/mlx4_main.c +++ b/sys/dev/mlx4/mlx4_core/mlx4_main.c @@ -386,6 +386,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) } } + dev->caps.map_clock_to_user = dev_cap->map_clock_to_user; dev->caps.uar_page_size = PAGE_SIZE; dev->caps.num_uars = dev_cap->uar_size / PAGE_SIZE; dev->caps.local_ca_ack_delay = dev_cap->local_ca_ack_delay; @@ -1872,6 +1873,11 @@ int mlx4_get_internal_clock_params(struct mlx4_dev *dev, if (mlx4_is_slave(dev)) return -ENOTSUPP; + if (!dev->caps.map_clock_to_user) { + mlx4_dbg(dev, "Map clock to user is not supported.\n"); + return -EOPNOTSUPP; + } + if (!params) return -EINVAL; diff --git a/sys/dev/mlx4/mlx4_ib/mlx4_ib_main.c b/sys/dev/mlx4/mlx4_ib/mlx4_ib_main.c index ef23f182bc28..e992400820c0 100644 --- a/sys/dev/mlx4/mlx4_ib/mlx4_ib_main.c +++ b/sys/dev/mlx4/mlx4_ib/mlx4_ib_main.c @@ -560,12 +560,9 @@ static int mlx4_ib_query_device(struct ib_device *ibdev, props->hca_core_clock = dev->dev->caps.hca_core_clock * 1000UL; props->timestamp_mask = 0xFFFFFFFFFFFFULL; - if (!mlx4_is_slave(dev->dev)) - err = mlx4_get_internal_clock_params(dev->dev, &clock_params); - if (uhw->outlen >= resp.response_length + sizeof(resp.hca_core_clock_offset)) { resp.response_length += sizeof(resp.hca_core_clock_offset); - if (!err && !mlx4_is_slave(dev->dev)) { + if (!mlx4_get_internal_clock_params(dev->dev, &clock_params)) { resp.comp_mask |= QUERY_DEVICE_RESP_MASK_TIMESTAMP; resp.hca_core_clock_offset = clock_params.offset % PAGE_SIZE; }