Skip to content

Commit d83edab

Browse files
yishaihrleon
authored andcommitted
RDMA/core: Introduce a DMAH object and its alloc/free APIs
Introduce a new DMA handle (DMAH) object along with its corresponding allocation and deallocation APIs. This DMAH object encapsulates attributes intended for use in DMA transactions. While its initial purpose is to support TPH functionality, it is designed to be extensible for future features such as DMA PCI multipath, PCI UIO configurations, PCI traffic class selection, and more. Further details: ---------------- We ensure that a caller requesting a DMA handle for a specific CPU ID is permitted to be scheduled on it. This prevent a potential security issue where a non privilege user may trigger DMA operations toward a CPU that it's not allowed to run on. We manage reference counting for the DMAH object and its consumers (e.g., memory regions) as will be detailed in subsequent patches in the series. Signed-off-by: Yishai Hadas <[email protected]> Reviewed-by: Edward Srouji <[email protected]> Link: https://patch.msgid.link/2cad097e849597e49d6b61e6865dba878257f371.1752752567.git.leon@kernel.org Signed-off-by: Leon Romanovsky <[email protected]>
1 parent 5b2e450 commit d83edab

File tree

9 files changed

+200
-0
lines changed

9 files changed

+200
-0
lines changed

drivers/infiniband/core/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ ib_umad-y := user_mad.o
3333
ib_uverbs-y := uverbs_main.o uverbs_cmd.o uverbs_marshall.o \
3434
rdma_core.o uverbs_std_types.o uverbs_ioctl.o \
3535
uverbs_std_types_cq.o \
36+
uverbs_std_types_dmah.o \
3637
uverbs_std_types_flow_action.o uverbs_std_types_dm.o \
3738
uverbs_std_types_mr.o uverbs_std_types_counters.o \
3839
uverbs_uapi.o uverbs_std_types_device.o \

drivers/infiniband/core/device.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2708,6 +2708,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
27082708
SET_DEVICE_OP(dev_ops, add_sub_dev);
27092709
SET_DEVICE_OP(dev_ops, advise_mr);
27102710
SET_DEVICE_OP(dev_ops, alloc_dm);
2711+
SET_DEVICE_OP(dev_ops, alloc_dmah);
27112712
SET_DEVICE_OP(dev_ops, alloc_hw_device_stats);
27122713
SET_DEVICE_OP(dev_ops, alloc_hw_port_stats);
27132714
SET_DEVICE_OP(dev_ops, alloc_mr);
@@ -2736,6 +2737,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
27362737
SET_DEVICE_OP(dev_ops, create_user_ah);
27372738
SET_DEVICE_OP(dev_ops, create_wq);
27382739
SET_DEVICE_OP(dev_ops, dealloc_dm);
2740+
SET_DEVICE_OP(dev_ops, dealloc_dmah);
27392741
SET_DEVICE_OP(dev_ops, dealloc_driver);
27402742
SET_DEVICE_OP(dev_ops, dealloc_mw);
27412743
SET_DEVICE_OP(dev_ops, dealloc_pd);
@@ -2833,6 +2835,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
28332835
SET_OBJ_SIZE(dev_ops, ib_ah);
28342836
SET_OBJ_SIZE(dev_ops, ib_counters);
28352837
SET_OBJ_SIZE(dev_ops, ib_cq);
2838+
SET_OBJ_SIZE(dev_ops, ib_dmah);
28362839
SET_OBJ_SIZE(dev_ops, ib_mw);
28372840
SET_OBJ_SIZE(dev_ops, ib_pd);
28382841
SET_OBJ_SIZE(dev_ops, ib_qp);

drivers/infiniband/core/rdma_core.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ extern const struct uapi_definition uverbs_def_obj_counters[];
156156
extern const struct uapi_definition uverbs_def_obj_cq[];
157157
extern const struct uapi_definition uverbs_def_obj_device[];
158158
extern const struct uapi_definition uverbs_def_obj_dm[];
159+
extern const struct uapi_definition uverbs_def_obj_dmah[];
159160
extern const struct uapi_definition uverbs_def_obj_flow_action[];
160161
extern const struct uapi_definition uverbs_def_obj_intf[];
161162
extern const struct uapi_definition uverbs_def_obj_mr[];

drivers/infiniband/core/restrack.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ static struct ib_device *res_to_dev(struct rdma_restrack_entry *res)
100100
return container_of(res, struct rdma_counter, res)->device;
101101
case RDMA_RESTRACK_SRQ:
102102
return container_of(res, struct ib_srq, res)->device;
103+
case RDMA_RESTRACK_DMAH:
104+
return container_of(res, struct ib_dmah, res)->device;
103105
default:
104106
WARN_ONCE(true, "Wrong resource tracking type %u\n", res->type);
105107
return NULL;
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2+
/*
3+
* Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved
4+
*/
5+
6+
#include "rdma_core.h"
7+
#include "uverbs.h"
8+
#include <rdma/uverbs_std_types.h>
9+
#include "restrack.h"
10+
11+
static int uverbs_free_dmah(struct ib_uobject *uobject,
12+
enum rdma_remove_reason why,
13+
struct uverbs_attr_bundle *attrs)
14+
{
15+
struct ib_dmah *dmah = uobject->object;
16+
int ret;
17+
18+
if (atomic_read(&dmah->usecnt))
19+
return -EBUSY;
20+
21+
ret = dmah->device->ops.dealloc_dmah(dmah, attrs);
22+
if (ret)
23+
return ret;
24+
25+
rdma_restrack_del(&dmah->res);
26+
kfree(dmah);
27+
return 0;
28+
}
29+
30+
static int UVERBS_HANDLER(UVERBS_METHOD_DMAH_ALLOC)(
31+
struct uverbs_attr_bundle *attrs)
32+
{
33+
struct ib_uobject *uobj =
34+
uverbs_attr_get(attrs, UVERBS_ATTR_ALLOC_DMAH_HANDLE)
35+
->obj_attr.uobject;
36+
struct ib_device *ib_dev = attrs->context->device;
37+
struct ib_dmah *dmah;
38+
int ret;
39+
40+
dmah = rdma_zalloc_drv_obj(ib_dev, ib_dmah);
41+
if (!dmah)
42+
return -ENOMEM;
43+
44+
if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_ALLOC_DMAH_CPU_ID)) {
45+
ret = uverbs_copy_from(&dmah->cpu_id, attrs,
46+
UVERBS_ATTR_ALLOC_DMAH_CPU_ID);
47+
if (ret)
48+
goto err;
49+
50+
if (!cpumask_test_cpu(dmah->cpu_id, current->cpus_ptr)) {
51+
ret = -EPERM;
52+
goto err;
53+
}
54+
55+
dmah->valid_fields |= BIT(IB_DMAH_CPU_ID_EXISTS);
56+
}
57+
58+
if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_ALLOC_DMAH_TPH_MEM_TYPE)) {
59+
dmah->mem_type = uverbs_attr_get_enum_id(attrs,
60+
UVERBS_ATTR_ALLOC_DMAH_TPH_MEM_TYPE);
61+
dmah->valid_fields |= BIT(IB_DMAH_MEM_TYPE_EXISTS);
62+
}
63+
64+
if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_ALLOC_DMAH_PH)) {
65+
ret = uverbs_copy_from(&dmah->ph, attrs,
66+
UVERBS_ATTR_ALLOC_DMAH_PH);
67+
if (ret)
68+
goto err;
69+
70+
/* Per PCIe spec 6.2-1.0, only the lowest two bits are applicable */
71+
if (dmah->ph & 0xFC) {
72+
ret = -EINVAL;
73+
goto err;
74+
}
75+
76+
dmah->valid_fields |= BIT(IB_DMAH_PH_EXISTS);
77+
}
78+
79+
dmah->device = ib_dev;
80+
dmah->uobject = uobj;
81+
atomic_set(&dmah->usecnt, 0);
82+
83+
rdma_restrack_new(&dmah->res, RDMA_RESTRACK_DMAH);
84+
rdma_restrack_set_name(&dmah->res, NULL);
85+
86+
ret = ib_dev->ops.alloc_dmah(dmah, attrs);
87+
if (ret) {
88+
rdma_restrack_put(&dmah->res);
89+
goto err;
90+
}
91+
92+
uobj->object = dmah;
93+
rdma_restrack_add(&dmah->res);
94+
uverbs_finalize_uobj_create(attrs, UVERBS_ATTR_ALLOC_DMAH_HANDLE);
95+
return 0;
96+
err:
97+
kfree(dmah);
98+
return ret;
99+
}
100+
101+
static const struct uverbs_attr_spec uverbs_dmah_mem_type[] = {
102+
[TPH_MEM_TYPE_VM] = {
103+
.type = UVERBS_ATTR_TYPE_PTR_IN,
104+
UVERBS_ATTR_NO_DATA(),
105+
},
106+
[TPH_MEM_TYPE_PM] = {
107+
.type = UVERBS_ATTR_TYPE_PTR_IN,
108+
UVERBS_ATTR_NO_DATA(),
109+
},
110+
};
111+
112+
DECLARE_UVERBS_NAMED_METHOD(
113+
UVERBS_METHOD_DMAH_ALLOC,
114+
UVERBS_ATTR_IDR(UVERBS_ATTR_ALLOC_DMAH_HANDLE,
115+
UVERBS_OBJECT_DMAH,
116+
UVERBS_ACCESS_NEW,
117+
UA_MANDATORY),
118+
UVERBS_ATTR_PTR_IN(UVERBS_ATTR_ALLOC_DMAH_CPU_ID,
119+
UVERBS_ATTR_TYPE(u32),
120+
UA_OPTIONAL),
121+
UVERBS_ATTR_ENUM_IN(UVERBS_ATTR_ALLOC_DMAH_TPH_MEM_TYPE,
122+
uverbs_dmah_mem_type,
123+
UA_OPTIONAL),
124+
UVERBS_ATTR_PTR_IN(UVERBS_ATTR_ALLOC_DMAH_PH,
125+
UVERBS_ATTR_TYPE(u8),
126+
UA_OPTIONAL));
127+
128+
DECLARE_UVERBS_NAMED_METHOD_DESTROY(
129+
UVERBS_METHOD_DMAH_FREE,
130+
UVERBS_ATTR_IDR(UVERBS_ATTR_FREE_DMA_HANDLE,
131+
UVERBS_OBJECT_DMAH,
132+
UVERBS_ACCESS_DESTROY,
133+
UA_MANDATORY));
134+
135+
DECLARE_UVERBS_NAMED_OBJECT(UVERBS_OBJECT_DMAH,
136+
UVERBS_TYPE_ALLOC_IDR(uverbs_free_dmah),
137+
&UVERBS_METHOD(UVERBS_METHOD_DMAH_ALLOC),
138+
&UVERBS_METHOD(UVERBS_METHOD_DMAH_FREE));
139+
140+
const struct uapi_definition uverbs_def_obj_dmah[] = {
141+
UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DMAH,
142+
UAPI_DEF_OBJ_NEEDS_FN(dealloc_dmah),
143+
UAPI_DEF_OBJ_NEEDS_FN(alloc_dmah)),
144+
{}
145+
};

drivers/infiniband/core/uverbs_uapi.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,7 @@ static const struct uapi_definition uverbs_core_api[] = {
631631
UAPI_DEF_CHAIN(uverbs_def_obj_cq),
632632
UAPI_DEF_CHAIN(uverbs_def_obj_device),
633633
UAPI_DEF_CHAIN(uverbs_def_obj_dm),
634+
UAPI_DEF_CHAIN(uverbs_def_obj_dmah),
634635
UAPI_DEF_CHAIN(uverbs_def_obj_flow_action),
635636
UAPI_DEF_CHAIN(uverbs_def_obj_intf),
636637
UAPI_DEF_CHAIN(uverbs_def_obj_mr),

include/rdma/ib_verbs.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include <rdma/signature.h>
4343
#include <uapi/rdma/rdma_user_ioctl.h>
4444
#include <uapi/rdma/ib_user_ioctl_verbs.h>
45+
#include <linux/pci-tph.h>
4546

4647
#define IB_FW_VERSION_NAME_MAX ETHTOOL_FWVERS_LEN
4748

@@ -1846,6 +1847,27 @@ struct ib_dm {
18461847
atomic_t usecnt;
18471848
};
18481849

1850+
/* bit values to mark existence of ib_dmah fields */
1851+
enum {
1852+
IB_DMAH_CPU_ID_EXISTS,
1853+
IB_DMAH_MEM_TYPE_EXISTS,
1854+
IB_DMAH_PH_EXISTS,
1855+
};
1856+
1857+
struct ib_dmah {
1858+
struct ib_device *device;
1859+
struct ib_uobject *uobject;
1860+
/*
1861+
* Implementation details of the RDMA core, don't use in drivers:
1862+
*/
1863+
struct rdma_restrack_entry res;
1864+
u32 cpu_id;
1865+
enum tph_mem_type mem_type;
1866+
atomic_t usecnt;
1867+
u8 ph;
1868+
u8 valid_fields; /* use IB_DMAH_XXX_EXISTS */
1869+
};
1870+
18491871
struct ib_mr {
18501872
struct ib_device *device;
18511873
struct ib_pd *pd;
@@ -2573,6 +2595,9 @@ struct ib_device_ops {
25732595
struct ib_dm_alloc_attr *attr,
25742596
struct uverbs_attr_bundle *attrs);
25752597
int (*dealloc_dm)(struct ib_dm *dm, struct uverbs_attr_bundle *attrs);
2598+
int (*alloc_dmah)(struct ib_dmah *ibdmah,
2599+
struct uverbs_attr_bundle *attrs);
2600+
int (*dealloc_dmah)(struct ib_dmah *dmah, struct uverbs_attr_bundle *attrs);
25762601
struct ib_mr *(*reg_dm_mr)(struct ib_pd *pd, struct ib_dm *dm,
25772602
struct ib_dm_mr_attr *attr,
25782603
struct uverbs_attr_bundle *attrs);
@@ -2730,6 +2755,7 @@ struct ib_device_ops {
27302755
DECLARE_RDMA_OBJ_SIZE(ib_ah);
27312756
DECLARE_RDMA_OBJ_SIZE(ib_counters);
27322757
DECLARE_RDMA_OBJ_SIZE(ib_cq);
2758+
DECLARE_RDMA_OBJ_SIZE(ib_dmah);
27332759
DECLARE_RDMA_OBJ_SIZE(ib_mw);
27342760
DECLARE_RDMA_OBJ_SIZE(ib_pd);
27352761
DECLARE_RDMA_OBJ_SIZE(ib_qp);

include/rdma/restrack.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ enum rdma_restrack_type {
5656
* @RDMA_RESTRACK_SRQ: Shared receive queue (SRQ)
5757
*/
5858
RDMA_RESTRACK_SRQ,
59+
/**
60+
* @RDMA_RESTRACK_DMAH: DMA handle
61+
*/
62+
RDMA_RESTRACK_DMAH,
5963
/**
6064
* @RDMA_RESTRACK_MAX: Last entry, used for array dclarations
6165
*/

include/uapi/rdma/ib_user_ioctl_cmds.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ enum uverbs_default_objects {
5555
UVERBS_OBJECT_DM,
5656
UVERBS_OBJECT_COUNTERS,
5757
UVERBS_OBJECT_ASYNC_EVENT,
58+
UVERBS_OBJECT_DMAH,
5859
};
5960

6061
enum {
@@ -240,6 +241,22 @@ enum uverbs_methods_dm {
240241
UVERBS_METHOD_DM_FREE,
241242
};
242243

244+
enum uverbs_attrs_alloc_dmah_cmd_attr_ids {
245+
UVERBS_ATTR_ALLOC_DMAH_HANDLE,
246+
UVERBS_ATTR_ALLOC_DMAH_CPU_ID,
247+
UVERBS_ATTR_ALLOC_DMAH_TPH_MEM_TYPE,
248+
UVERBS_ATTR_ALLOC_DMAH_PH,
249+
};
250+
251+
enum uverbs_attrs_free_dmah_cmd_attr_ids {
252+
UVERBS_ATTR_FREE_DMA_HANDLE,
253+
};
254+
255+
enum uverbs_methods_dmah {
256+
UVERBS_METHOD_DMAH_ALLOC,
257+
UVERBS_METHOD_DMAH_FREE,
258+
};
259+
243260
enum uverbs_attrs_reg_dm_mr_cmd_attr_ids {
244261
UVERBS_ATTR_REG_DM_MR_HANDLE,
245262
UVERBS_ATTR_REG_DM_MR_OFFSET,

0 commit comments

Comments
 (0)