Skip to content

Commit 7b5d753

Browse files
jasowangmstsirkin
authored andcommitted
vhost: fine grain userspace memory accessors
This is used to hide the metadata address from virtqueue helpers. This will allow to implement a vmap based fast accessing to metadata. Signed-off-by: Jason Wang <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent 1ab5d13 commit 7b5d753

File tree

1 file changed

+77
-17
lines changed

1 file changed

+77
-17
lines changed

drivers/vhost/vhost.c

Lines changed: 77 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,34 @@ static inline void __user *__vhost_get_user(struct vhost_virtqueue *vq,
887887
ret; \
888888
})
889889

890+
static inline int vhost_put_avail_event(struct vhost_virtqueue *vq)
891+
{
892+
return vhost_put_user(vq, cpu_to_vhost16(vq, vq->avail_idx),
893+
vhost_avail_event(vq));
894+
}
895+
896+
static inline int vhost_put_used(struct vhost_virtqueue *vq,
897+
struct vring_used_elem *head, int idx,
898+
int count)
899+
{
900+
return vhost_copy_to_user(vq, vq->used->ring + idx, head,
901+
count * sizeof(*head));
902+
}
903+
904+
static inline int vhost_put_used_flags(struct vhost_virtqueue *vq)
905+
906+
{
907+
return vhost_put_user(vq, cpu_to_vhost16(vq, vq->used_flags),
908+
&vq->used->flags);
909+
}
910+
911+
static inline int vhost_put_used_idx(struct vhost_virtqueue *vq)
912+
913+
{
914+
return vhost_put_user(vq, cpu_to_vhost16(vq, vq->last_used_idx),
915+
&vq->used->idx);
916+
}
917+
890918
#define vhost_get_user(vq, x, ptr, type) \
891919
({ \
892920
int ret; \
@@ -925,6 +953,43 @@ static void vhost_dev_unlock_vqs(struct vhost_dev *d)
925953
mutex_unlock(&d->vqs[i]->mutex);
926954
}
927955

956+
static inline int vhost_get_avail_idx(struct vhost_virtqueue *vq,
957+
__virtio16 *idx)
958+
{
959+
return vhost_get_avail(vq, *idx, &vq->avail->idx);
960+
}
961+
962+
static inline int vhost_get_avail_head(struct vhost_virtqueue *vq,
963+
__virtio16 *head, int idx)
964+
{
965+
return vhost_get_avail(vq, *head,
966+
&vq->avail->ring[idx & (vq->num - 1)]);
967+
}
968+
969+
static inline int vhost_get_avail_flags(struct vhost_virtqueue *vq,
970+
__virtio16 *flags)
971+
{
972+
return vhost_get_avail(vq, *flags, &vq->avail->flags);
973+
}
974+
975+
static inline int vhost_get_used_event(struct vhost_virtqueue *vq,
976+
__virtio16 *event)
977+
{
978+
return vhost_get_avail(vq, *event, vhost_used_event(vq));
979+
}
980+
981+
static inline int vhost_get_used_idx(struct vhost_virtqueue *vq,
982+
__virtio16 *idx)
983+
{
984+
return vhost_get_used(vq, *idx, &vq->used->idx);
985+
}
986+
987+
static inline int vhost_get_desc(struct vhost_virtqueue *vq,
988+
struct vring_desc *desc, int idx)
989+
{
990+
return vhost_copy_from_user(vq, desc, vq->desc + idx, sizeof(*desc));
991+
}
992+
928993
static int vhost_new_umem_range(struct vhost_umem *umem,
929994
u64 start, u64 size, u64 end,
930995
u64 userspace_addr, int perm)
@@ -1862,8 +1927,7 @@ EXPORT_SYMBOL_GPL(vhost_log_write);
18621927
static int vhost_update_used_flags(struct vhost_virtqueue *vq)
18631928
{
18641929
void __user *used;
1865-
if (vhost_put_user(vq, cpu_to_vhost16(vq, vq->used_flags),
1866-
&vq->used->flags) < 0)
1930+
if (vhost_put_used_flags(vq))
18671931
return -EFAULT;
18681932
if (unlikely(vq->log_used)) {
18691933
/* Make sure the flag is seen before log. */
@@ -1880,8 +1944,7 @@ static int vhost_update_used_flags(struct vhost_virtqueue *vq)
18801944

18811945
static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event)
18821946
{
1883-
if (vhost_put_user(vq, cpu_to_vhost16(vq, vq->avail_idx),
1884-
vhost_avail_event(vq)))
1947+
if (vhost_put_avail_event(vq))
18851948
return -EFAULT;
18861949
if (unlikely(vq->log_used)) {
18871950
void __user *used;
@@ -1917,7 +1980,7 @@ int vhost_vq_init_access(struct vhost_virtqueue *vq)
19171980
r = -EFAULT;
19181981
goto err;
19191982
}
1920-
r = vhost_get_used(vq, last_used_idx, &vq->used->idx);
1983+
r = vhost_get_used_idx(vq, &last_used_idx);
19211984
if (r) {
19221985
vq_err(vq, "Can't access used idx at %p\n",
19231986
&vq->used->idx);
@@ -2116,7 +2179,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,
21162179
last_avail_idx = vq->last_avail_idx;
21172180

21182181
if (vq->avail_idx == vq->last_avail_idx) {
2119-
if (unlikely(vhost_get_avail(vq, avail_idx, &vq->avail->idx))) {
2182+
if (unlikely(vhost_get_avail_idx(vq, &avail_idx))) {
21202183
vq_err(vq, "Failed to access avail idx at %p\n",
21212184
&vq->avail->idx);
21222185
return -EFAULT;
@@ -2143,8 +2206,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,
21432206

21442207
/* Grab the next descriptor number they're advertising, and increment
21452208
* the index we've seen. */
2146-
if (unlikely(vhost_get_avail(vq, ring_head,
2147-
&vq->avail->ring[last_avail_idx & (vq->num - 1)]))) {
2209+
if (unlikely(vhost_get_avail_head(vq, &ring_head, last_avail_idx))) {
21482210
vq_err(vq, "Failed to read head: idx %d address %p\n",
21492211
last_avail_idx,
21502212
&vq->avail->ring[last_avail_idx % vq->num]);
@@ -2179,8 +2241,7 @@ int vhost_get_vq_desc(struct vhost_virtqueue *vq,
21792241
i, vq->num, head);
21802242
return -EINVAL;
21812243
}
2182-
ret = vhost_copy_from_user(vq, &desc, vq->desc + i,
2183-
sizeof desc);
2244+
ret = vhost_get_desc(vq, &desc, i);
21842245
if (unlikely(ret)) {
21852246
vq_err(vq, "Failed to get descriptor: idx %d addr %p\n",
21862247
i, vq->desc + i);
@@ -2273,7 +2334,7 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq,
22732334

22742335
start = vq->last_used_idx & (vq->num - 1);
22752336
used = vq->used->ring + start;
2276-
if (vhost_copy_to_user(vq, used, heads, count * sizeof *used)) {
2337+
if (vhost_put_used(vq, heads, start, count)) {
22772338
vq_err(vq, "Failed to write used");
22782339
return -EFAULT;
22792340
}
@@ -2315,8 +2376,7 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads,
23152376

23162377
/* Make sure buffer is written before we update index. */
23172378
smp_wmb();
2318-
if (vhost_put_user(vq, cpu_to_vhost16(vq, vq->last_used_idx),
2319-
&vq->used->idx)) {
2379+
if (vhost_put_used_idx(vq)) {
23202380
vq_err(vq, "Failed to increment used idx");
23212381
return -EFAULT;
23222382
}
@@ -2349,7 +2409,7 @@ static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
23492409

23502410
if (!vhost_has_feature(vq, VIRTIO_RING_F_EVENT_IDX)) {
23512411
__virtio16 flags;
2352-
if (vhost_get_avail(vq, flags, &vq->avail->flags)) {
2412+
if (vhost_get_avail_flags(vq, &flags)) {
23532413
vq_err(vq, "Failed to get flags");
23542414
return true;
23552415
}
@@ -2363,7 +2423,7 @@ static bool vhost_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
23632423
if (unlikely(!v))
23642424
return true;
23652425

2366-
if (vhost_get_avail(vq, event, vhost_used_event(vq))) {
2426+
if (vhost_get_used_event(vq, &event)) {
23672427
vq_err(vq, "Failed to get used event idx");
23682428
return true;
23692429
}
@@ -2408,7 +2468,7 @@ bool vhost_vq_avail_empty(struct vhost_dev *dev, struct vhost_virtqueue *vq)
24082468
if (vq->avail_idx != vq->last_avail_idx)
24092469
return false;
24102470

2411-
r = vhost_get_avail(vq, avail_idx, &vq->avail->idx);
2471+
r = vhost_get_avail_idx(vq, &avail_idx);
24122472
if (unlikely(r))
24132473
return false;
24142474
vq->avail_idx = vhost16_to_cpu(vq, avail_idx);
@@ -2444,7 +2504,7 @@ bool vhost_enable_notify(struct vhost_dev *dev, struct vhost_virtqueue *vq)
24442504
/* They could have slipped one in as we were doing that: make
24452505
* sure it's written, then check again. */
24462506
smp_mb();
2447-
r = vhost_get_avail(vq, avail_idx, &vq->avail->idx);
2507+
r = vhost_get_avail_idx(vq, &avail_idx);
24482508
if (r) {
24492509
vq_err(vq, "Failed to check avail idx at %p: %d\n",
24502510
&vq->avail->idx, r);

0 commit comments

Comments
 (0)