Skip to content

Commit 0bbe306

Browse files
jasowangmstsirkin
authored andcommitted
vhost: factor out IOTLB
This patch factors out IOTLB into a dedicated module in order to be reused by other modules like vringh. User may choose to enable the automatic retiring by specifying VHOST_IOTLB_FLAG_RETIRE flag to fit for the case of vhost device IOTLB implementation. Signed-off-by: Jason Wang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent 792a4f2 commit 0bbe306

File tree

8 files changed

+315
-181
lines changed

8 files changed

+315
-181
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17766,6 +17766,7 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git
1776617766
S: Maintained
1776717767
F: drivers/vhost/
1776817768
F: include/uapi/linux/vhost.h
17769+
F: include/linux/vhost_iotlb.h
1776917770

1777017771
VIRTIO INPUT DRIVER
1777117772
M: Gerd Hoffmann <[email protected]>

drivers/vhost/Kconfig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
# SPDX-License-Identifier: GPL-2.0-only
2+
config VHOST_IOTLB
3+
tristate
4+
help
5+
Generic IOTLB implementation for vhost and vringh.
6+
27
config VHOST_RING
38
tristate
49
help
@@ -67,4 +72,5 @@ config VHOST_CROSS_ENDIAN_LEGACY
6772
adds some overhead, it is disabled by default.
6873

6974
If unsure, say "N".
75+
7076
endif

drivers/vhost/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@ vhost_vsock-y := vsock.o
1111
obj-$(CONFIG_VHOST_RING) += vringh.o
1212

1313
obj-$(CONFIG_VHOST) += vhost.o
14+
15+
obj-$(CONFIG_VHOST_IOTLB) += vhost_iotlb.o
16+
vhost_iotlb-y := iotlb.o

drivers/vhost/iotlb.c

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/* Copyright (C) 2020 Red Hat, Inc.
3+
* Author: Jason Wang <[email protected]>
4+
*
5+
* IOTLB implementation for vhost.
6+
*/
7+
#include <linux/slab.h>
8+
#include <linux/vhost_iotlb.h>
9+
#include <linux/module.h>
10+
11+
#define MOD_VERSION "0.1"
12+
#define MOD_DESC "VHOST IOTLB"
13+
#define MOD_AUTHOR "Jason Wang <[email protected]>"
14+
#define MOD_LICENSE "GPL v2"
15+
16+
#define START(map) ((map)->start)
17+
#define LAST(map) ((map)->last)
18+
19+
INTERVAL_TREE_DEFINE(struct vhost_iotlb_map,
20+
rb, __u64, __subtree_last,
21+
START, LAST, static inline, vhost_iotlb_itree);
22+
23+
/**
24+
* vhost_iotlb_map_free - remove a map node and free it
25+
* @iotlb: the IOTLB
26+
* @map: the map that want to be remove and freed
27+
*/
28+
void vhost_iotlb_map_free(struct vhost_iotlb *iotlb,
29+
struct vhost_iotlb_map *map)
30+
{
31+
vhost_iotlb_itree_remove(map, &iotlb->root);
32+
list_del(&map->link);
33+
kfree(map);
34+
iotlb->nmaps--;
35+
}
36+
EXPORT_SYMBOL_GPL(vhost_iotlb_map_free);
37+
38+
/**
39+
* vhost_iotlb_add_range - add a new range to vhost IOTLB
40+
* @iotlb: the IOTLB
41+
* @start: start of the IOVA range
42+
* @last: last of IOVA range
43+
* @addr: the address that is mapped to @start
44+
* @perm: access permission of this range
45+
*
46+
* Returns an error last is smaller than start or memory allocation
47+
* fails
48+
*/
49+
int vhost_iotlb_add_range(struct vhost_iotlb *iotlb,
50+
u64 start, u64 last,
51+
u64 addr, unsigned int perm)
52+
{
53+
struct vhost_iotlb_map *map;
54+
55+
if (last < start)
56+
return -EFAULT;
57+
58+
if (iotlb->limit &&
59+
iotlb->nmaps == iotlb->limit &&
60+
iotlb->flags & VHOST_IOTLB_FLAG_RETIRE) {
61+
map = list_first_entry(&iotlb->list, typeof(*map), link);
62+
vhost_iotlb_map_free(iotlb, map);
63+
}
64+
65+
map = kmalloc(sizeof(*map), GFP_ATOMIC);
66+
if (!map)
67+
return -ENOMEM;
68+
69+
map->start = start;
70+
map->size = last - start + 1;
71+
map->last = last;
72+
map->addr = addr;
73+
map->perm = perm;
74+
75+
iotlb->nmaps++;
76+
vhost_iotlb_itree_insert(map, &iotlb->root);
77+
78+
INIT_LIST_HEAD(&map->link);
79+
list_add_tail(&map->link, &iotlb->list);
80+
81+
return 0;
82+
}
83+
EXPORT_SYMBOL_GPL(vhost_iotlb_add_range);
84+
85+
/**
86+
* vring_iotlb_del_range - delete overlapped ranges from vhost IOTLB
87+
* @iotlb: the IOTLB
88+
* @start: start of the IOVA range
89+
* @last: last of IOVA range
90+
*/
91+
void vhost_iotlb_del_range(struct vhost_iotlb *iotlb, u64 start, u64 last)
92+
{
93+
struct vhost_iotlb_map *map;
94+
95+
while ((map = vhost_iotlb_itree_iter_first(&iotlb->root,
96+
start, last)))
97+
vhost_iotlb_map_free(iotlb, map);
98+
}
99+
EXPORT_SYMBOL_GPL(vhost_iotlb_del_range);
100+
101+
/**
102+
* vhost_iotlb_alloc - add a new vhost IOTLB
103+
* @limit: maximum number of IOTLB entries
104+
* @flags: VHOST_IOTLB_FLAG_XXX
105+
*
106+
* Returns an error is memory allocation fails
107+
*/
108+
struct vhost_iotlb *vhost_iotlb_alloc(unsigned int limit, unsigned int flags)
109+
{
110+
struct vhost_iotlb *iotlb = kzalloc(sizeof(*iotlb), GFP_KERNEL);
111+
112+
if (!iotlb)
113+
return NULL;
114+
115+
iotlb->root = RB_ROOT_CACHED;
116+
iotlb->limit = limit;
117+
iotlb->nmaps = 0;
118+
iotlb->flags = flags;
119+
INIT_LIST_HEAD(&iotlb->list);
120+
121+
return iotlb;
122+
}
123+
EXPORT_SYMBOL_GPL(vhost_iotlb_alloc);
124+
125+
/**
126+
* vhost_iotlb_reset - reset vhost IOTLB (free all IOTLB entries)
127+
* @iotlb: the IOTLB to be reset
128+
*/
129+
void vhost_iotlb_reset(struct vhost_iotlb *iotlb)
130+
{
131+
vhost_iotlb_del_range(iotlb, 0ULL, 0ULL - 1);
132+
}
133+
EXPORT_SYMBOL_GPL(vhost_iotlb_reset);
134+
135+
/**
136+
* vhost_iotlb_free - reset and free vhost IOTLB
137+
* @iotlb: the IOTLB to be freed
138+
*/
139+
void vhost_iotlb_free(struct vhost_iotlb *iotlb)
140+
{
141+
if (iotlb) {
142+
vhost_iotlb_reset(iotlb);
143+
kfree(iotlb);
144+
}
145+
}
146+
EXPORT_SYMBOL_GPL(vhost_iotlb_free);
147+
148+
/**
149+
* vhost_iotlb_itree_first - return the first overlapped range
150+
* @iotlb: the IOTLB
151+
* @start: start of IOVA range
152+
* @end: end of IOVA range
153+
*/
154+
struct vhost_iotlb_map *
155+
vhost_iotlb_itree_first(struct vhost_iotlb *iotlb, u64 start, u64 last)
156+
{
157+
return vhost_iotlb_itree_iter_first(&iotlb->root, start, last);
158+
}
159+
EXPORT_SYMBOL_GPL(vhost_iotlb_itree_first);
160+
161+
/**
162+
* vhost_iotlb_itree_first - return the next overlapped range
163+
* @iotlb: the IOTLB
164+
* @start: start of IOVA range
165+
* @end: end of IOVA range
166+
*/
167+
struct vhost_iotlb_map *
168+
vhost_iotlb_itree_next(struct vhost_iotlb_map *map, u64 start, u64 last)
169+
{
170+
return vhost_iotlb_itree_iter_next(map, start, last);
171+
}
172+
EXPORT_SYMBOL_GPL(vhost_iotlb_itree_next);
173+
174+
MODULE_VERSION(MOD_VERSION);
175+
MODULE_DESCRIPTION(MOD_DESC);
176+
MODULE_AUTHOR(MOD_AUTHOR);
177+
MODULE_LICENSE(MOD_LICENSE);

drivers/vhost/net.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1587,7 +1587,7 @@ static long vhost_net_reset_owner(struct vhost_net *n)
15871587
struct socket *tx_sock = NULL;
15881588
struct socket *rx_sock = NULL;
15891589
long err;
1590-
struct vhost_umem *umem;
1590+
struct vhost_iotlb *umem;
15911591

15921592
mutex_lock(&n->dev.mutex);
15931593
err = vhost_dev_check_owner(&n->dev);

0 commit comments

Comments
 (0)