aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/vhost/vhost.c
diff options
context:
space:
mode:
authorJason Wang <jasowang@redhat.com>2019-05-24 04:12:17 -0400
committerMichael S. Tsirkin <mst@redhat.com>2019-06-05 16:23:53 -0400
commitfeebcaeac79ad86fb289ef55fa92f4a97ab8314e (patch)
tree653fe9ef4cb8914c9aef72f1074140462fd7c286 /drivers/vhost/vhost.c
parent4942e8254d93b31ea14cf63a9dfd10a8112caafa (diff)
vhost: factor out setting vring addr and num
Factoring vring address and num setting which needs special care for accelerating vq metadata accessing. Signed-off-by: Jason Wang <jasowang@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Diffstat (limited to 'drivers/vhost/vhost.c')
-rw-r--r--drivers/vhost/vhost.c177
1 files changed, 103 insertions, 74 deletions
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 30afc79d551e..e27d1da5f979 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1486,6 +1486,104 @@ err:
1486 return -EFAULT; 1486 return -EFAULT;
1487} 1487}
1488 1488
1489static long vhost_vring_set_num(struct vhost_dev *d,
1490 struct vhost_virtqueue *vq,
1491 void __user *argp)
1492{
1493 struct vhost_vring_state s;
1494
1495 /* Resizing ring with an active backend?
1496 * You don't want to do that. */
1497 if (vq->private_data)
1498 return -EBUSY;
1499
1500 if (copy_from_user(&s, argp, sizeof s))
1501 return -EFAULT;
1502
1503 if (!s.num || s.num > 0xffff || (s.num & (s.num - 1)))
1504 return -EINVAL;
1505 vq->num = s.num;
1506
1507 return 0;
1508}
1509
1510static long vhost_vring_set_addr(struct vhost_dev *d,
1511 struct vhost_virtqueue *vq,
1512 void __user *argp)
1513{
1514 struct vhost_vring_addr a;
1515
1516 if (copy_from_user(&a, argp, sizeof a))
1517 return -EFAULT;
1518 if (a.flags & ~(0x1 << VHOST_VRING_F_LOG))
1519 return -EOPNOTSUPP;
1520
1521 /* For 32bit, verify that the top 32bits of the user
1522 data are set to zero. */
1523 if ((u64)(unsigned long)a.desc_user_addr != a.desc_user_addr ||
1524 (u64)(unsigned long)a.used_user_addr != a.used_user_addr ||
1525 (u64)(unsigned long)a.avail_user_addr != a.avail_user_addr)
1526 return -EFAULT;
1527
1528 /* Make sure it's safe to cast pointers to vring types. */
1529 BUILD_BUG_ON(__alignof__ *vq->avail > VRING_AVAIL_ALIGN_SIZE);
1530 BUILD_BUG_ON(__alignof__ *vq->used > VRING_USED_ALIGN_SIZE);
1531 if ((a.avail_user_addr & (VRING_AVAIL_ALIGN_SIZE - 1)) ||
1532 (a.used_user_addr & (VRING_USED_ALIGN_SIZE - 1)) ||
1533 (a.log_guest_addr & (VRING_USED_ALIGN_SIZE - 1)))
1534 return -EINVAL;
1535
1536 /* We only verify access here if backend is configured.
1537 * If it is not, we don't as size might not have been setup.
1538 * We will verify when backend is configured. */
1539 if (vq->private_data) {
1540 if (!vq_access_ok(vq, vq->num,
1541 (void __user *)(unsigned long)a.desc_user_addr,
1542 (void __user *)(unsigned long)a.avail_user_addr,
1543 (void __user *)(unsigned long)a.used_user_addr))
1544 return -EINVAL;
1545
1546 /* Also validate log access for used ring if enabled. */
1547 if ((a.flags & (0x1 << VHOST_VRING_F_LOG)) &&
1548 !log_access_ok(vq->log_base, a.log_guest_addr,
1549 sizeof *vq->used +
1550 vq->num * sizeof *vq->used->ring))
1551 return -EINVAL;
1552 }
1553
1554 vq->log_used = !!(a.flags & (0x1 << VHOST_VRING_F_LOG));
1555 vq->desc = (void __user *)(unsigned long)a.desc_user_addr;
1556 vq->avail = (void __user *)(unsigned long)a.avail_user_addr;
1557 vq->log_addr = a.log_guest_addr;
1558 vq->used = (void __user *)(unsigned long)a.used_user_addr;
1559
1560 return 0;
1561}
1562
1563static long vhost_vring_set_num_addr(struct vhost_dev *d,
1564 struct vhost_virtqueue *vq,
1565 unsigned int ioctl,
1566 void __user *argp)
1567{
1568 long r;
1569
1570 mutex_lock(&vq->mutex);
1571
1572 switch (ioctl) {
1573 case VHOST_SET_VRING_NUM:
1574 r = vhost_vring_set_num(d, vq, argp);
1575 break;
1576 case VHOST_SET_VRING_ADDR:
1577 r = vhost_vring_set_addr(d, vq, argp);
1578 break;
1579 default:
1580 BUG();
1581 }
1582
1583 mutex_unlock(&vq->mutex);
1584
1585 return r;
1586}
1489long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp) 1587long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp)
1490{ 1588{
1491 struct file *eventfp, *filep = NULL; 1589 struct file *eventfp, *filep = NULL;
@@ -1495,7 +1593,6 @@ long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *arg
1495 struct vhost_virtqueue *vq; 1593 struct vhost_virtqueue *vq;
1496 struct vhost_vring_state s; 1594 struct vhost_vring_state s;
1497 struct vhost_vring_file f; 1595 struct vhost_vring_file f;
1498 struct vhost_vring_addr a;
1499 u32 idx; 1596 u32 idx;
1500 long r; 1597 long r;
1501 1598
@@ -1508,26 +1605,14 @@ long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *arg
1508 idx = array_index_nospec(idx, d->nvqs); 1605 idx = array_index_nospec(idx, d->nvqs);
1509 vq = d->vqs[idx]; 1606 vq = d->vqs[idx];
1510 1607
1608 if (ioctl == VHOST_SET_VRING_NUM ||
1609 ioctl == VHOST_SET_VRING_ADDR) {
1610 return vhost_vring_set_num_addr(d, vq, ioctl, argp);
1611 }
1612
1511 mutex_lock(&vq->mutex); 1613 mutex_lock(&vq->mutex);
1512 1614
1513 switch (ioctl) { 1615 switch (ioctl) {
1514 case VHOST_SET_VRING_NUM:
1515 /* Resizing ring with an active backend?
1516 * You don't want to do that. */
1517 if (vq->private_data) {
1518 r = -EBUSY;
1519 break;
1520 }
1521 if (copy_from_user(&s, argp, sizeof s)) {
1522 r = -EFAULT;
1523 break;
1524 }
1525 if (!s.num || s.num > 0xffff || (s.num & (s.num - 1))) {
1526 r = -EINVAL;
1527 break;
1528 }
1529 vq->num = s.num;
1530 break;
1531 case VHOST_SET_VRING_BASE: 1616 case VHOST_SET_VRING_BASE:
1532 /* Moving base with an active backend? 1617 /* Moving base with an active backend?
1533 * You don't want to do that. */ 1618 * You don't want to do that. */
@@ -1553,62 +1638,6 @@ long vhost_vring_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *arg
1553 if (copy_to_user(argp, &s, sizeof s)) 1638 if (copy_to_user(argp, &s, sizeof s))
1554 r = -EFAULT; 1639 r = -EFAULT;
1555 break; 1640 break;
1556 case VHOST_SET_VRING_ADDR:
1557 if (copy_from_user(&a, argp, sizeof a)) {
1558 r = -EFAULT;
1559 break;
1560 }
1561 if (a.flags & ~(0x1 << VHOST_VRING_F_LOG)) {
1562 r = -EOPNOTSUPP;
1563 break;
1564 }
1565 /* For 32bit, verify that the top 32bits of the user
1566 data are set to zero. */
1567 if ((u64)(unsigned long)a.desc_user_addr != a.desc_user_addr ||
1568 (u64)(unsigned long)a.used_user_addr != a.used_user_addr ||
1569 (u64)(unsigned long)a.avail_user_addr != a.avail_user_addr) {
1570 r = -EFAULT;
1571 break;
1572 }
1573
1574 /* Make sure it's safe to cast pointers to vring types. */
1575 BUILD_BUG_ON(__alignof__ *vq->avail > VRING_AVAIL_ALIGN_SIZE);
1576 BUILD_BUG_ON(__alignof__ *vq->used > VRING_USED_ALIGN_SIZE);
1577 if ((a.avail_user_addr & (VRING_AVAIL_ALIGN_SIZE - 1)) ||
1578 (a.used_user_addr & (VRING_USED_ALIGN_SIZE - 1)) ||
1579 (a.log_guest_addr & (VRING_USED_ALIGN_SIZE - 1))) {
1580 r = -EINVAL;
1581 break;
1582 }
1583
1584 /* We only verify access here if backend is configured.
1585 * If it is not, we don't as size might not have been setup.
1586 * We will verify when backend is configured. */
1587 if (vq->private_data) {
1588 if (!vq_access_ok(vq, vq->num,
1589 (void __user *)(unsigned long)a.desc_user_addr,
1590 (void __user *)(unsigned long)a.avail_user_addr,
1591 (void __user *)(unsigned long)a.used_user_addr)) {
1592 r = -EINVAL;
1593 break;
1594 }
1595
1596 /* Also validate log access for used ring if enabled. */
1597 if ((a.flags & (0x1 << VHOST_VRING_F_LOG)) &&
1598 !log_access_ok(vq->log_base, a.log_guest_addr,
1599 sizeof *vq->used +
1600 vq->num * sizeof *vq->used->ring)) {
1601 r = -EINVAL;
1602 break;
1603 }
1604 }
1605
1606 vq->log_used = !!(a.flags & (0x1 << VHOST_VRING_F_LOG));
1607 vq->desc = (void __user *)(unsigned long)a.desc_user_addr;
1608 vq->avail = (void __user *)(unsigned long)a.avail_user_addr;
1609 vq->log_addr = a.log_guest_addr;
1610 vq->used = (void __user *)(unsigned long)a.used_user_addr;
1611 break;
1612 case VHOST_SET_VRING_KICK: 1641 case VHOST_SET_VRING_KICK:
1613 if (copy_from_user(&f, argp, sizeof f)) { 1642 if (copy_from_user(&f, argp, sizeof f)) {
1614 r = -EFAULT; 1643 r = -EFAULT;